Extensions/VFX Naming Convention
ComfyUI Extension

VFX Naming Convention

Build VFX-compliant filename prefixes (SHOW_SEQ_SHOT_task_ven_v) for Save Image and video saver nodes.

By vctrprzvfx·Created about a month ago·Updated about a month ago· 11
vctrprzvfx/ComfyUI-VFX-Naming
Nodes1
On cloudLocal install
CategoryVFX/naming
Stars11
Updatedabout a month ago
Readme

ComfyUI VFX Naming Convention

A single node that composes a VFX-compliant filename_prefix string for Save Image, Save Image (Advanced), and video saver nodes (VideoHelperSuite Video Combine, etc.), so ComfyUI output drops straight into a film or episodic VFX pipeline instead of ComfyUI_00001_.png.

Based on the VFX Naming Convention paper by Victor Perez, VFX Supervisor — generic, with no show-specific codes baked in.

SHW_SEQ_0010_comp_vnd_v001/
    SHW_SEQ_0010_comp_vnd_v001.1001.exr

The naming convention

Every file exchanged with or within the VFX department follows one string. Each department is responsible for naming the material it generates; transfers that do not meet the convention should be treated as undelivered.

Structure

AAA_AAA_####_aaaa_aaa_v###.####.aaa
<SHOW CODE>_<SEQUENCE CODE>_<SHOT NUMBER>_<TASK>_<VENDOR ID>_<VERSION NUMBER>.<FRAME NUMBER>.<FILE EXTENSION>

Components

| Component | Specification | |---|---| | <SHOW CODE> | 3 alphabetic characters (letters), uppercase | | _ | 1 underscore separator (fixed) | | <SEQUENCE CODE> | 3 alphabetic characters (letters), uppercase | | _ | 1 underscore separator (fixed) | | <SHOT NUMBER> | 4 digits (padded numbers), in increments of tens | | _ | 1 underscore separator (fixed) | | <TASK> | 4 alphabetic characters (letters), lowercase  <sup>1</sup> | | _ | 1 underscore separator (fixed) | | <VENDOR ID> | 3 alphabetic characters (letters), lowercase  <sup>2</sup> | | _ | 1 underscore separator (fixed) | | <VERSION NUMBER> | v prefixed + 3 digits (padded numbers) | | . | 1 period separator (fixed) | | <FRAME NUMBER> | 4 digits (padded numbers) — first frame 1001 | | . | 1 period separator (fixed) | | <FILE EXTENSION> | 3 alphabetic characters (letters), lowercase |

<sup>1</sup> Plates provided by the Lab use fewer characters (usually 2) and may include numbers; this is described under Plates below. Finalised VFX shots delivered by a vendor use a special <TASK> format — see Vendor exceptions.

<sup>2</sup> Plates provided by the Lab do not contain the <VENDOR ID> component, nor the corresponding underscore separator between components.

Filename examples

SHW_SEQ_0010_comp_vnd_v001.1001.exr
SHW_SEQ_0125_prev_vnd_v001.1001.exr

Shot ID and task denominators

SHW_SEQ_0010_comp_vnd_v001.1001.exr
└────── shot id ─────┘└─ task denominators ─┘

| Part | Meaning | |---|---| | Shot ID | The unique shot name — show, sequence and shot number | | Task denominators | Define the work, task or element contained in the file |

Read as: show SHW, sequence SEQ, shot 1, task compositing, vendor vnd, version 1, frame 1001 (first frame of the range), OpenEXR.

Vendor exceptions

VFX vendors must add the <VENDOR ID> tag assigned to them for any exchange of files out of their facility. The vendor code is assigned by the VFX Producer and communicated in advance.

For complete and approved VFX shots — marked as Final — the status in the <TASK> component is FINAL, in uppercase:

SHW_SEQ_0030_FINAL_vnd_v012.1234.exr

Folder structure

File sequences must be contained in folders named after the Shot ID and the Task and Version Number denominators — that is, the filename without the frame number and extension:

SHW_SEQ_0010_comp_vnd_v001/
    SHW_SEQ_0010_comp_vnd_v001.1001.exr
    SHW_SEQ_0010_comp_vnd_v001.1002.exr

Plates — Lab inputs to VFX

In this context, plates are image sequences derived from images captured by a camera and processed by the laboratory to be provided to the VFX vendors for visual effects work.

Plates do not contain the <VENDOR ID> component, nor its underscore separator. For plates the <TASK> component is an exception of only 2 characters, and shall have one of the following values:

| Task | Plate type | |---|---| | mp | Main Plate — when only one element is required to produce the final VFX work | | bg | Background plate — for VFX work requiring multiple elements. Background plates carry layer identification, for example bg or bg02 | | fg | Foreground plate — for VFX work requiring multiple elements. Foreground plates include layer information, for example fg12 | | el | Element plate — isolated elements of the shot: partial composites in multi-vendor shots, or rotoscoped and CG elements delivered at production's request | | cp | Clean Plate — to be used for cleanup work | | rp | Reference Plate — such as lighting reference |

There is some redundancy between fg and el. Where ambiguous, the choice is user preference.

LMTs, CDLs and any other LUTs must carry the same name as the plate they refer to, with the exception of the extension:

SHW_SEQ_0010_mp_v001.1001.exr
SHW_SEQ_0010_mp_v001.1001.cube
SHW_SEQ_0010_cp_v001.1001.exr
SHW_SEQ_0010_cp_v001.1001.cdl
SHW_SEQ_0010_bg02_v001.1001.exr

Frame ranges

| | | |---|---| | First frame of the plate | 1001 | | First frame of the edit range | 1011 | | Frame handles | 10 head + 10 tail | | Work range | Matches the plate range |

VFX work must be executed for the whole work range, including the handles. A 44 frame shot therefore runs 1001–1064:

 1001         1011                     1054         1064
  |____________|________________________|____________|
  |  handles   |       edit range       |  handles   |
  |   10 fr    |         44 fr          |   10 fr    |
  |____________|________________________|____________|
  |                                                  |
  |<------- work range = plate range = 64 fr ------->|

Editorial should be aware of the handles when reconforming VFX shots in the timeline. An eyeballing check is advised.

Node

VFX Naming Convention (Filename Prefix) — category VFX/naming.

Inputs

| Input | Purpose | |---|---| | show_code, sequence_code | 3-letter codes, auto-uppercased | | shot_number | arrows snap to the nearest shot ending in 0; any number can be typed; padded to shot_padding | | task | dropdown of task codes, plate types, FINAL, or (custom) | | task_custom | free task code, used when task is (custom) | | plate_layer | 0 = none; 2 turns bg into bg02 | | vendor_id | 3 letters; leave empty for lab plates | | version | padded to version_padding | | sequence_subfolder | on = basename/basename, off = basename | | parent_path | optional sub-path, e.g. SHW/SEQ or %date:yyyy-MM-dd% | | first_frame | work-range head; convention is 1001 (10 head + 10 tail handles) | | file_extension | drives the extension and example_filename outputs | | strict | on = abort on any violation; off = auto-correct and warn | | schema | which JSON schema in schemas/ to render | | template_override | override the schema's template for this node only | | custom_tokens | extra name=value tokens available to the template |

Outputs

| Output | Example | |---|---| | filename_prefix | SHW_SEQ_0010_comp_vnd_v001/SHW_SEQ_0010_comp_vnd_v001 | | folder_name | SHW_SEQ_0010_comp_vnd_v001 | | basename | SHW_SEQ_0010_comp_vnd_v001 | | shot_id | SHW_SEQ_0010 | | extension | exr (lowercase, no leading dot) | | example_filename | SHW_SEQ_0010_comp_vnd_v001.1001.exr | | first_frame | 1001 (INT — feed frame-range inputs) | | report | full breakdown plus any validation warnings |

Wire filename_prefix into the saver's filename_prefix widget (convert it to an input first: right-click the Save node → Convert widget to input, or drag from this node's output onto the widget in recent frontends).

Schemas — the convention is configuration

No naming rule is hardcoded in the logic. Which tokens exist, how each one is cased, padded and validated, the delimiters, the order of the tokens and how many folder levels they render into all live in JSON under schemas/. naming_schema.py is only the engine that loads and renders them.

Pick one with the schema widget. Four ship with the node:

| Schema | Renders | |---|---| | vfx_default | SHW_SEQ_0010_comp_vnd_v001/SHW_SEQ_0010_comp_vnd_v001 | | vfx_flat | SHW_SEQ_0010_comp_vnd_v001 (no sequence folder) | | studio_nested | SHW/SEQ/0010/comp-vnd/v001-0010-comp-vnd | | episodic_dotted | SHW/ep101/SEQ.0010/SHW.SEQ.0010.comp.vp.v001 |

Writing your own

Drop a JSON file in schemas/ and it appears in the dropdown after a restart:

{
  "label": "My studio",
  "tokens": {
    "show":    {"label": "Show code", "charset": "alpha", "case": "upper", "length": 4},
    "shot":    {"label": "Shot", "type": "int", "pad": 3},
    "version": {"label": "Version", "type": "int", "pad": 2, "prefix": "V"}
  },
  "folders": ["{show}", "{seq}"],
  "file": "{show}-{shot}[-{vendor}]-{version}",
  "filename": "{basename}.{frame}.{ext}",
  "rules": [
    {"when": {"token": "task", "matches": "(mp|bg|fg|el|cp|rp)\\d*"},
     "omit": ["vendor"], "note": "Lab plates carry no vendor id"}
  ]
}

Token specs — charset (alpha / alnum / any), case (upper / lower), length for an exact character count, type: "int" with pad, prefix (the v in v001), pattern for an extra regex check, and optional: true to allow it to be empty.

Templates — folders is a list of path levels (any depth), file is the basename, filename is the full name used for the example_filename output.

| Syntax | Meaning | |---|---| | {token} | substitute a token | | {token:upper} | modifiers: upper, lower, or a pad width like 04 | | [ ... ] | optional group — dropped whole when every token inside is empty, which is how a component and its delimiter disappear together | | / | folder separator, any number of levels | | anything else | a literal, so delimiters are whatever you type |

Rules drop tokens that cannot coexist. The shipped rule is the lab-plate one: when task matches a plate type, vendor is omitted along with its delimiter.

Per-node overrides

template_override replaces the schema's templates for one node — handy for a one-off without writing a file:

{show}/{seq}/{shot}/{task}/{show}_{shot}_{version}

custom_tokens adds tokens the widgets do not cover, one name=value per line, referenced as {episode}:

episode=101
artist=vp

Important: what ComfyUI appends

ComfyUI's own savers always append their own counter and extension:

file = f"{filename_with_batch_num}_{counter:05}_.png"   # nodes.py, SaveImage

So a prefix of SHW_SEQ_0010_comp_vnd_v001 lands on disk as:

SHW_SEQ_0010_comp_vnd_v001/SHW_SEQ_0010_comp_vnd_v001_00001_.png

The name, folder and every component up to the version are exactly correct; the .1001.exr frame/extension tail is controlled by the saver, not the prefix, and stock ComfyUI uses _00001_ counters starting at 1 instead of .1001. Nodes with an explicit extension/format widget (Save Image Advanced variants, VHS Video Combine) honour the format you pick there.

To get literal basename.1001.exr on disk you need a saver that writes the frame token itself — that is a separate node, not something a prefix string can do. extension, example_filename and first_frame are provided so you can drive one, or feed the format widget of a saver that accepts a string.

Shot number stepping

The +/- buttons move the shot number in tens, matching the convention, but any number can be typed in manually — 15, 125, 7. Off-grid values are accepted even in strict mode; they only add an advisory note to the report output. (The convention's own example SHW_SEQ_0125_prev_vnd_v001 is off-grid.)

Pressing +/- always lands on the nearest shot number ending in 0, in the direction pressed — from 98, + goes to 100 and - goes to 90, rather than dragging the off-grid number along to 108. On-grid values step normally (20 -> 30).

Both behaviours need the bundled web/vfx_naming.js. ComfyUI's INT widget uses one option (step2) for both the increment and for snapping committed values onto that grid, so a plain "step": 10 would round a typed 15 up to 20. Python declares step 1 (always free to type), and the extension supplies the stepping.

With Comfy.VueNodes enabled the widget renders as a DOM component whose +/- buttons do model = clamp(model +/- step) and commit by calling widget.callback(value) directly — never setValue() or onClick(). The grid step is therefore applied on pointerdown, by setting step2 to the exact distance to the next grid point in that direction (the option is reactive, and a pointerdown precedes the click by a full task, so the component re-renders with the new step before it computes the value). The wrapped callback then redirects an armed change onto the grid as a safety net — which is also what makes the keyboard Up/Down arrows snap, since no re-render happens between keydown and the component's handler.

Verified against a live ComfyUI 1.49.6: 20 stepping cases, free-form typing, and no effect on the node's other INT widgets or on other nodes.

Install

ComfyUI Manager — Install via Git URL, paste this repository's URL.

Manually — clone into your custom_nodes folder and restart ComfyUI:

cd ComfyUI/custom_nodes
git clone https://github.com/vctrprzvfx/ComfyUI-VFX-Naming.git

No dependencies beyond the Python standard library. After restarting, add the node from the VFX/naming category. If the shot-number stepping behaves oddly after an update, hard-refresh the browser (Cmd/Ctrl+Shift+R) — the bundled JavaScript is cached.

Credits

Naming convention and node by Victor Perez, Visual Effects Supervisor — victorperez.online

The schema-driven design — keeping the configuration separate from the logic, so studios can vary nesting depth, delimiters and token order — was suggested by Sam Hodge.

Released under the MIT License.