Nodes/Otonx's Custom Nodes/OTX KSampler Feeder
ComfyUI Node

OTX KSampler Feeder

One node to keep both SDXL samplers in sync

By budihartono·Created 3 years ago·Updated 2 years ago· 1
OTX KSampler Feeder
    • noise_seed
    • steps
    • cfg
    • base_end_at_step
    noise_seed0
    steps20
    cfg8.00
    base_steps_portion0.8

    OTX KSampler Feeder is the one genuinely clever node in Otonx's Custom Nodes, and it exists for a workflow that's mostly a historical artifact: the two-pass SDXL base-plus-refiner setup. Its job is to act as a central value store for the parameters both samplers share - seed, steps, cfg - plus one derived value: the exact step where the base sampler stops and the refiner takes over. One node instead of a rat's nest of primitive boxes feeding two KSampler (Advanced) nodes.

    It was built around the two-sampler pattern from FollowFoxAI's "Advanced SDXL Workflows in ComfyUI" series (Part 4), and it's by Budi Hartono, a solo author with a small pack and basically no community footprint. The README fairly warns the nodes change intermittently. Whether this workflow is still worth running is a separate question - more on that below.

    How it works

    The mechanism is one line of math wrapped around a pass-through:

    def pass_parameters(self, base_steps_portion, noise_seed, steps, cfg):
        base_end_at_step = int(steps * base_steps_portion)
        return noise_seed, steps, cfg, base_end_at_step
    

    You type in your total steps and a base_steps_portion (default 0.8), and the node works out base_end_at_step - where the base sampler finishes and the refiner starts. So with 30 steps and 0.8, the base runs steps 0–23 and the refiner handles 24–29. One widget, and the split always matches the total, which is exactly the kind of bookkeeping that goes wrong when you hand-edit start_at_step on two nodes.

    The inputs and outputs that matter

    Four inputs, and each maps to a real KSampler (Advanced) field:

    • noise_seed (INT, up to 2^64) - wire into both samplers' noise_seed so they denoise from the same noise. This is the point of the node: identical seeds, no duplicated widgets.
    • steps (INT, default 20) - into both samplers' steps.
    • cfg (FLOAT, default 8.0) - into both samplers' cfg.
    • base_steps_portion (FLOAT, 0–1, default 0.8, steps of 0.1) - the knob that sets the split.

    And four outputs, all named to match what they feed: noise_seed, steps, cfg, and base_end_at_step. Wire the last one into the base sampler's end_at_step and the refiner's start_at_step - the refiner picks up exactly where the base left off.

    Two small gotchas. First, int() truncates: with 27 steps and 0.8 you get 21 (21.6 → 21), so the actual split is a hair before the fraction suggests - harmless, but know it's truncation, not rounding. Second, set base_steps_portion to 1.0 and the refiner gets start_at_step equal to the total, i.e. no refiner work at all - useful as an A/B switch, confusing if you set it by accident.

    Is the base/refiner workflow worth it?

    The honest context: the SDXL refiner was the community's most famous good idea that went nowhere. Fine-tuned checkpoints matured fast, and the consensus (as captured in the SDXL knowledge panel) is that the refiner "survives only in occasional hires-fix workflows" - the quality gain didn't justify the extra pass. So this node is aimed at a pattern most people abandoned. If you run the classic base+refiner SDXL graph, the feeder genuinely simplifies it. If you don't, there's no reason to adopt the pattern just because the node exists.

    Installing it

    Zero dependencies, pure Python, no model downloads. Install via ComfyUI Manager (search "Otonx"), or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/budihartono/comfyui_otonx_nodes
    

    Restart ComfyUI and it appears under OtonxPack.

    Common issues

    • Refiner not doing anything - check base_steps_portion isn't at 1.0, and that base_end_at_step actually reaches the refiner's start_at_step.
    • Split doesn't match what you expect - remember the truncation: the base end is int(steps × portion), not a rounded value.

    It's a tidy little node for a niche workflow. If you're on that workflow, it earns its place; if you're on SDXL without a refiner, it's a well-made answer to a question you're not asking.

    CategoryOtonxPack

    Inputs (4)

    NameTypeDefaultDescription
    noise_seedINT00–18446744073709550000
    stepsINT201–10000
    cfgFLOAT8.000–100
    base_steps_portionFLOAT0.80–1

    Outputs (4)

    NameTypeDescription
    noise_seedINT
    stepsINT
    cfgFLOAT
    base_end_at_stepINT