Nodes/comfyui-obvpm/Value Presets (obvpm)
ComfyUI Node

Value Presets (obvpm)

Stop retyping cfg, steps, and denoise on every workflow

By chanon·Created about a month ago·Updated a day ago· 40
Value Presets (obvpm)
    • bundle
    schema# one field per line: name: type [range] [= default] # types: text | int | float | bool | choice a, b, c | @Node.input steps: int 1..200 = 20 cfg: float 0..100 = 5.0 sampler: @SamplerName.sampler_name
    presetcustom
    values{}
    presets{}
    names

    ComfyUI gives you the "one seed, five samplers" trick via convert-to-input, but there's a hole in it: every value you want to share - cfg, steps, denoise, the resize guide - needs its own primitive node, and none of them remember anything between sessions. Value Presets is the pack's answer to that. It's a single node where you type named numbers like cfg: 7, steps: 28, denoise: 0.6, get a typed output socket per field, and can save the whole batch to a local library and load it back with one click. It ships in the same pack as its sibling Size Presets, and it's basically the "named values" version of that idea.

    The real hook is that presets are saved with categories and names, so "SDXL-fast" and "refine-pass" become one-click loads instead of a pile of primitive nodes you drag around and re-enter every time you reopen a workflow. This is the kind of node you'll shrug at until you've rebuilt your sampler settings from a screenshot for the fifth time.

    How it actually works

    The node has exactly one input in the schema, fields_json, and one output pair (v1v16), all typed * (wildcard). That sounds odd, but it's the trick: ComfyUI sockets are fixed at node-definition time, so a dynamic field list has to live somewhere serializable. All your state is a JSON array of {name, type, value} objects sitting in that one multiline string - up to 16 fields - and the bundled frontend JS renders each object as a friendly row with a name box, an INT/FLOAT type badge, a value field, and a gear for min/max/step limits. The backend unpacks the JSON and returns one number per slot, padding unused slots with 0.0, and the frontend labels each * socket as INT or FLOAT so ComfyUI lets you wire it straight into a sampler widget. Clever, and worth knowing about if you ever wonder why editing sometimes looks like JSON flickering in the background. The author also keys IS_CHANGED on fields_json, so the cache invalidates the moment you tweak a value - no stale generations.

    The bits you actually set

    You won't hand-edit the JSON. In practice you interact with the rendered rows:

    • Add field → pick blank (then INT or FLOAT) or grab a definition from the field library, which stores reusable defs with min/max/step, category, and notes.
    • Type is locked after you create the field - if you wanted FLOAT and made an INT, you replace it via the type badge rather than renaming it.
    • Gear → set limits and optionally save the field definition to the shared library.

    Outputs v1v16 wire into any node widget you've converted to input (right-click → convert). One worthwhile workflow: define cfg, steps, denoise, save it as "portrait-2" in a category, and load it into every project that uses the same recipe.

    Installing it

    Same pack, same story as Size Presets: either search "comfyui-size-presets" in ComfyUI Manager, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/StoneZol/comfyui-size-presets.git
    

    Then restart ComfyUI. Good news for a change: no pip dependencies, no model downloads. It's Python 3.8+ stdlib plus SQLite, and presets live in db/presets.sqlite, auto-created on first use (unique per category + preset name). The node appears under the Size Presets category in the node menu.

    Gotchas worth knowing

    The pack is young - 2.0.0 landed days ago and reworked the whole value model - so treat early versions with a little caution. A couple of things that bit people before the 2.0.0 fix: edits and deletes used to not survive a browser refresh because fields_json didn't stay serializable. That's fixed now, but if you're on an older build and "lose" changes, update the pack. Also, all 16 output slots exist even when you only define three fields, and empty ones emit 0.0 - wire the ones you care about and ignore the rest. Blank nodes are allowed (you can delete every field and start over), but duplicate field names get rejected, so name carefully. And remember this node only emits numbers: it won't reach inside a sampler's logic, it just feeds the values you've already converted to inputs.

    Categoryobvpm/bundle

    Inputs (5)

    NameTypeDefaultDescription
    schemaSTRING# one field per line: name: type [range] [= default] # types: text | int | float | bool | choice a, b, c | @Node.input steps: int 1..200 = 20 cfg: float 0..100 = 5.0 sampler: @SamplerName.sampler_name The template: one field per line, written name: type [range] [= default]. Types are text, int, float, bool, 'choice a, b, c', and @Node.input to borrow another node's dropdown. Lines starting with # are ignored. A default follows '=', so a choice cannot contain one.
    presetSTRINGcustomWhich saved set is loaded. 'custom' is whatever you have set by hand; the name is a label on the values, which are what actually runs.
    valuesoptSTRING{}
    presetsoptSTRING{}
    namesoptSTRING

    Outputs (1)

    NameTypeDescription
    bundleOBVPM_BUNDLEThe fields as one value, keyed by name, in schema order.