Nodes/comfyui-ageshift/πŸŽ‚ Age Range Batch
ComfyUI Node

πŸŽ‚ Age Range Batch

The JSONL Factory That Drives Your Age-Progression Run

By aadebugerΒ·Created 3 months agoΒ·Updated 3 months agoΒ· 0
πŸŽ‚ Age Range Batch
    • prompts_jsonl
    • ages_csv
    • count
    β—„ages_csv5,15,25,45,65β–Ί
    β—„subjectpersonβ–Ί
    β—„genderunspecifiedβ–Ί
    β—„stylephotorealistic portrait, sharp focus, natural lightingβ–Ί
    β—„extra_positivesame identityβ–Ί

    AgeRangeBatch is the batch-mode cousin of AgePromptBuilder, and the honest thing to say up front is that it's aimed at the CLI, not the graph. Give it a comma-separated list of ages - 5,15,25,45,65 by default - and it emits one JSONL line per age: {"age": 5, "band": "child", "prompt": "a 5 year old ..."}. That's the whole trick. It's the data generator that the pack's cli/age_shift_cli.py consumes to render an age progression in a single command, and it exists because ComfyUI evaluates one prompt per submission - you can't loop a KSampler inside the graph, so something has to build the batch of prompts for you.

    If you're a UI-only user who wants to age one face to one target age, skip this node and use AgePromptBuilder instead. If your goal is "here's a face, give me a 5 β†’ 15 β†’ 25 β†’ 45 β†’ 65 sequence," this is the node whose output the batch script loops over.

    How it works

    It reuses the exact same age→feature lookup table as AgePromptBuilder (that's the pack's _types.py, twenty age ranges of concrete descriptors - "young toddler, round face, big bright eyes" at 5, "deeply weathered and wrinkled face" at 85). It parses your ages_csv, silently dropping anything that isn't a clean integer, maps each age to its band and feature phrase, and joins them into JSONL. Crucially it does not include the anti-drift negative logic that AgePromptBuilder has - it only builds positives, because the CLI composes the full conditioning graph itself.

    Inputs and outputs

    • ages_csv - the only required input. Comma-separated integers, 5,15,25,45,65 by default. This is what you'll actually edit.
    • subject, gender, style, extra_positive - same knobs as AgePromptBuilder. Default gender is unspecified, and same advice applies: set subject to "boy" or "girl" for child ages or you'll get the awkward "male man" phrasing.

    Outputs:

    • prompts_jsonl (STRING) - the newline-separated JSON records; the CLI's data source.
    • ages_csv (STRING) - the cleaned, normalized age list (invalid entries removed).
    • count (INT) - how many valid ages made it through, handy as a quick sanity check.

    Running the batch

    The CLI talks to a running ComfyUI server over its HTTP + websocket API - including a remote one, which is the point of the --ip flag - so it works from a laptop pointed at a beefy box:

    uv run --script cli/age_shift_cli.py face.jpg \
        --target-ages 5,15,25,45,65 \
        --gender male --subject man \
        --pulid-weight 0.95 --guidance 3.0 --steps 28 --seed 42 \
        --ip 192.168.1.50 --out ./out
    

    Output lands as ./out/age_005_*.png, age_015_*.png, and so on. The script uses PEP 723 inline dependencies, so uv run --script installs what it needs automatically - and the README calls out the specific trap that the missing module is websocket-client, not websocket (a separate abandoned package that won't satisfy the import).

    Install and gotchas

    Same pack install as the rest: clone aadebuger/ComfyUI-AgeShift into custom_nodes, uv pip install -r requirements.txt, restart. The batch path additionally needs the full PuLID-Flux + Flux weight stack on the server (see the AgePromptBuilder article for that dance - the InsightFace antelopev2 manual placement is the part people get wrong).

    The classic failure is No module named 'websocket' when running the script directly - the README's fix is uv pip install websocket-client, or just lean on uv run --script to let it resolve. The other usual suspects: no --ip (defaults to 127.0.0.1:8188), and forgetting that each age is a separate full generation, so a five-age run is five times the sampling time. Lock the seed across ages or you'll get five different sub-identities instead of one person at five ages - that's the single most common reason a progression looks like a cast, not a life.

    CategoryπŸŽ‚ AgeShift

    Inputs (5)

    NameTypeDefaultDescription
    ages_csvSTRING5,15,25,45,65β€”
    subjectoptSTRINGpersonβ€”
    genderoptCOMBOunspecified4 options: unspecified, male, female, non-binary
    styleoptSTRINGphotorealistic portrait, sharp focus, natural lightingβ€”
    extra_positiveoptSTRINGsame identityβ€”

    Outputs (3)

    NameTypeDescription
    prompts_jsonlSTRINGβ€”
    ages_csvSTRINGβ€”
    countINTβ€”