{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "H3 Ref Chain plans", "description": "Two documents. `shot_plan` goes in the shot_plan widget, `ref_plan` in the ref_plan widget. Generated by tools/gen_schema.py from the installed node -- do not edit by hand.", "type": "object", "required": [ "shot_plan", "ref_plan" ], "properties": { "shot_plan": { "type": "object", "required": [ "shots" ], "additionalProperties": false, "properties": { "shots": { "type": "array", "minItems": 1, "items": { "type": "object", "required": [ "beat" ], "additionalProperties": false, "properties": { "id": { "type": "string", "description": "Stable name. Generated if absent." }, "beat": { "type": "string", "description": "What happens THIS hop. Shot 1 is the whole opening; every later shot is only the new beat." }, "directives": { "type": "object", "additionalProperties": false, "properties": { "join": { "type": "string", "enum": [ "continuous", "hard_cut", "match_cut" ], "description": "continuous: The camera and the action carry straight on from the pinned frames in one unbroken take. | match_cut: The shot changes on a matched movement, the new framing picking up the same gesture already underway. | hard_cut: A clean cut opens a new setup, the same place a moment later." }, "camera": { "type": "string", "enum": [ "handheld", "hold", "orbit", "pan_follow", "pull_back", "push_in" ], "description": "hold: The camera holds its position throughout. | pan_follow: The camera pans smoothly to follow the movement, holding it in frame. | push_in: The camera pushes slowly in. | pull_back: The camera draws slowly back, opening the frame. | orbit: The camera arcs slowly around the action. | handheld: The camera carries a light handheld float." }, "framing": { "type": "string", "enum": [ "close", "keep", "medium", "wide" ], "description": "keep: The framing stays as it is. | wide: A wide shot with the full room in view. | medium: A medium shot from the waist up. | close: A close shot, head and shoulders filling the frame." }, "pace": { "type": "string", "enum": [ "brisk", "slow", "steady" ], "description": "slow: Everything moves at an unhurried pace. | steady: The action moves at a steady, even pace. | brisk: The action moves briskly." }, "tail": { "type": "string", "enum": [ "hold", "ongoing", "settle" ], "description": "ongoing: The action is still underway as the clip ends. | settle: The movement eases to a rest and stays there. | hold: The final position holds steady through the last moments.", "default": "ongoing" } }, "description": "Compiled in the order join, camera, framing, pace, tail. `join` is ignored on shot 1." }, "prose": { "type": "string", "description": "Appended verbatim, for anything the vocabulary lacks. Phrase it affirmatively." }, "seed": { "type": "integer" }, "steps": { "type": "integer" }, "duration": { "type": "string", "enum": [ "5 s", "7 s", "8 s", "10 s", "15 s" ] }, "locked": { "type": "boolean", "description": "Reuse this hop's cached render even when its inputs changed. Needs cache_hops=on." }, "tone": { "type": "string", "enum": [ "free", "rebase" ], "description": "Opt out of tone_compensate=anchor's pull toward hop 1's exposure. 'free' skips it for this hop; 'rebase' also moves the anchor onto this hop, for a scene that is deliberately darker or brighter from here on. Omit it unless that is the case." }, "anchor": { "type": "string", "enum": [ "restart" ], "description": "Re-anchor the chain on the start image at this hop instead of relaying the previous one. Bounds the quality decay on a long chain: every hop otherwise inherits its predecessor's most settled frames, so motion and lighting response fade the further in you go. It is a CUT -- the hop opens on the start image's pose, not where the previous hop ended -- so pair it with join 'hard_cut' and write the beat as a fresh start. Needs a start image, never on shot 1, and only on a chain long enough to need one (roughly every 4-6 hops)." }, "refs": { "type": "array", "items": { "type": "string" }, "description": "Which register stills ride this hop, as @tags without the @. Omit the field for the register default (unscheduled stills on chain starts, off continuations). An empty list is explicit none -- how you drop identity stills on a pin-less restart. A filled list is those tags only, in that order." } } }, "description": "One shot per hop. The shot count IS the hop count." } } }, "ref_plan": { "type": "object", "required": [ "refs" ], "additionalProperties": false, "properties": { "refs": { "type": "array", "items": { "type": "object", "required": [ "tag" ], "additionalProperties": false, "properties": { "tag": { "type": "string", "pattern": "^[A-Za-z0-9_]+$", "description": "Unique. Written into beats as @tag." }, "file": { "type": "string", "description": "Basename under ComfyUI/input/h3_refs. Never a path." }, "slot": { "type": "integer", "description": "Derived from list position. Do not author it; present only for legacy plans." }, "subject": { "type": "integer", "minimum": 1, "description": "Groups pictures OF THE SAME PERSON. Two different people under one number makes the model render the average of their faces." }, "retention": { "type": "string", "enum": [ "fully_preserved", "partially_copy", "reference" ], "description": "fully_preserved: face, bone structure, and hairstyle carry over exactly | partially_copy: the garment and its cut carry over, moving naturally with the body | reference: the layout, surfaces, and light carry over as the setting" }, "desc": { "type": "string" }, "shots": { "type": "array", "items": { "type": "integer", "minimum": 1 }, "minItems": 1, "description": "1-based hops this picture rides on. OMITTING IT MEANS HOP 1 ONLY on a continuation chain -- a plate shot elsewhere riding a later hop beats the frame pin." }, "mp": { "type": "number", "minimum": 0, "maximum": 16.0, "description": "Per-reference pixel budget in MEGApixels, set by the person on the rail. Do not author it: omit the field. It is here so a hand-written plan can carry one, and a written value is discarded on the pinned path. A set value has a 0.3 MP floor and a 16 MP ceiling; 0 means no cap." } } }, "maxItems": 9, "description": "At most 9 pictures on any one hop. Keep the whole list to 9 and that always holds." }, "subjects": { "type": "object", "patternProperties": { "^[0-9]+$": { "type": "object", "additionalProperties": false, "required": [ "name", "locked" ], "properties": { "name": { "type": "string", "minLength": 1, "description": "Plain prose that replaces the @tag from hop 2 on, e.g. 'the cook'. Never an @tag." }, "locked": { "type": "string", "minLength": 1, "description": "What must not change. This is what survives on a hop where the photograph is absent." }, "context": { "type": "string", "description": "Situational state that should persist -- wardrobe, what they are holding." } } } }, "additionalProperties": false, "description": "Keyed by subject number, as a STRING. Every subject here must be claimed by at least one ref, or the plan is rejected." } } } }, "x-duration-frames": { "5 s": 124, "7 s": 175, "8 s": 192, "10 s": 243, "15 s": 362 }, "x-rules": [ "cfg is 1.0 with no negative branch: the prompt is ADDITIVE. Anything named is added; nothing can be removed by mentioning it. Never write a negation.", "Never name the thing you want to end. 'stops talking' keeps them talking. Write the state as a pose plus a sound.", "H3 always generates audio. Silence must be written AS a sound -- room tone, a refrigerator, a single click.", "Ambience must be narrowband. 'faint street noise' renders as hiss; 'the low hum of the refrigerator' renders as a refrigerator.", "A state change belongs at the END of the previous shot. Every hop opens holding the frames it was handed.", "Shot 1 establishes everything. Later shots carry ONLY the new beat -- never re-describe the face, the clothes or the room.", "Write @tags into the action line. Describing a reference in the register does not make the model use it.", "Set `tail` to settle or hold on the FINAL shot, or the model is told action is still underway at the last frame and invents something to satisfy it." ] }