Nodes/ComfyUI-PromptMaker-PNGTuber/PNGTuber Quality Asset Builder (Image/Video)
ComfyUI Node

PNGTuber Quality Asset Builder (Image/Video)

Qwen-generated mouths, a THA3 idle loop, and a QA contact sheet that shows its work

By hobi2k·Created 3 months ago·Updated 3 months ago· 0
PNGTuber Quality Asset Builder (Image/Video)
    • bundle_manifest
    • mouth_track
    • mouth_dir
    • preview_contact
    source_pathinput.png
    output_dir
    asset_idpngtuber_quality_asset
    source_modeauto
    sprite_size512
    track_quad_scale1.25
    erase_scale1.18
    qwen_mask_scale0.72
    seed42
    make_tha3_looptrue
    tha3_repo
    tha3_skill_scripts
    fps30
    duration_seconds6.0
    tha3_variantseparable_float
    upscale_framestrue
    upscale_target_px1024
    upscale_model4x-UltraSharp.pth

    The upload-to-bundle node gets you a rig fast. This is the node you reach for when you care what it looks like. PNGTuberQualityAssetBuilder is the high-effort path: instead of cutting mouth shapes out of a video that may not articulate well, it generates them with a local Qwen image-edit model, erases the source mouth properly, optionally renders a THA3 idle loop so you have a natural mouthless animation, and - the part I like most - always writes a QA contact sheet that composites the generated mouths back onto the mouthless face so you can actually see whether it's a disaster before you ship it.

    Image or video

    Point source_path at either, and let source_mode sit on auto. Two behaviors:

    • Image input (the common PNGTuber case - you have one good transparent character render): the node localizes the mouth, erases it, runs Qwen/eigen five times (closed/half/open/e/u) on the full source image with only the mouth area masked, and writes runtime sprites plus the overlay contact. If make_tha3_loop is on, it renders a mouthless idle loop from the erased image.
    • Video input: Qwen generates identity-stable mouth sprites from the first frame while the video supplies the per-frame mouth track. That's a deliberate design choice - sprite identity stays consistent instead of cutting different mouths from different animation frames.

    The quality rules are baked in: Qwen sees the whole face and character context, not a detached crop; mouth localization has to pass size sanity checks before a bundle is accepted; and the returned preview_contact is the overlay QA contact, not a raw sprite dump.

    Inputs that matter

    • source_path / asset_id / output_dir - where the input lives and where the bundle goes (empty output_dir = ComfyUI output).
    • sprite_size / track_quad_scale / erase_scale / qwen_mask_scale / seed - the geometry and generation controls. Defaults are sane; qwen_mask_scale (0.72) controls how big the edit mask is relative to the mouth.
    • make_tha3_loop - the big one. true by default, and it's the piece that needs external tools. tha3_repo points at a checkout of the talking-head-anime-3-demo repo, tha3_skill_scripts at the ai-live2d-tha helper scripts (env vars THA3_REPO / THA3_SKILL_SCRIPTS are the fallback), and if either is missing it errors with a clear message. Set tha3_variant (separable_float is the default), fps, duration_seconds.
    • upscale_frames / upscale_target_px / upscale_model - the THA3 loop frames get upscaled (default 4x-UltraSharp.pth from your upscale_models folder) before encoding to webm + h264.

    Outputs: bundle_manifest, mouth_track, mouth_dir, and preview_contact - all paths. The bundle is pngtuber.qualityAssetBundle.v1.

    Install and honest expectations

    Same pack install as the rest (Manager, or clone + pip install -r requirements.txt, restart). But unlike the plain video path, this node has real heavy dependencies:

    • The local Qwen image-edit stack - the Qwen-Image-Edit model (GGUF or bf16), a Qwen text encoder + VAE, and the TextEncodeQwenImageEditPlus node. Multi-gigabyte downloads, same stack the "eigen" paths all share.
    • The THA3 repo and helper scripts for the idle loop.
    • An upscaler model for upscale_frames.

    First runs also hit the "eigen" cache cold, so a 6-second THA3 loop plus five Qwen generations is not a five-second queue - budget for it. The upside is the QA gate: if the overlay contact shows the generated mouths sliding off the face or wrong-sized, don't ship - re-run with a bigger erase_scale or a manual bbox rather than tweaking blindly. It refuses obviously invalid mouth localization precisely so you don't ship a rig that looks broken on stream.

    CategoryPNGTuber/Quality Builder

    Inputs (18)

    NameTypeDefaultDescription
    source_pathSTRINGinput.png
    output_dirSTRING
    asset_idSTRINGpngtuber_quality_asset
    source_modeCOMBOauto3 options: auto, image, video
    sprite_sizeINT512128–2048
    track_quad_scaleFLOAT1.251–4
    erase_scaleFLOAT1.181–2.5
    qwen_mask_scaleFLOAT0.720.3–2.5
    seedINT420–2147483647
    make_tha3_loopBOOLEANtrue
    tha3_repoSTRING
    tha3_skill_scriptsSTRING
    fpsFLOAT301–120
    duration_secondsFLOAT6.01–30
    tha3_variantCOMBOseparable_float4 options: separable_float, separable_half, standard_float, standard_half
    upscale_framesBOOLEANtrue
    upscale_target_pxINT1024512–2048
    upscale_modelSTRING4x-UltraSharp.pth

    Outputs (4)

    NameTypeDescription
    bundle_manifestSTRING
    mouth_trackSTRING
    mouth_dirSTRING
    preview_contactSTRING