Nodes/Strata-T8/Strata 结构化分镜 / JSON
ComfyUI Node

Strata 结构化分镜 / JSON

Storyboard JSON that gets validated, not hoped for

By T8mars·Created 21 days ago·Updated 10 days ago· 20
Strata 结构化分镜 / JSON
  • connection
  • json
  • shot_prompts
  • text_list
  • usage_json
◄prompt—►
◄schema{"type": "object", "required": ["shots"], "additionalProperties": false, "properties": {"shots": {"type": "array", "minItems": 1, "maxItems": 64, "items": {"type": "object", "required": ["subject", "action", "scene", "camera", "duration", "prompt"], "additionalProperties": false, "properties": {"subject": {"type": "string", "minLength": 1}, "action": {"type": "string", "minLength": 1}, "scene": {"type": "string", "minLength": 1}, "camera": {"type": "string", "minLength": 1}, "prompt": {"type": "string", "minLength": 1}, "duration": {"type": "number", "minimum": 0.1, "maximum": 600}}}}}}►
◄systemConvert the story into concrete sequential shots. Each prompt describes one visible shot. Return the requested JSON.►
◄repair_attempts0►
◄max_tokens1024►
◄temperature0.70►
◄top_p0.95►
◄top_k20►
◄seed0►
◄reasoning_effort▾►
◄refresh0►

Asking a local model for JSON is easy. Getting JSON your workflow can depend on is the hard part, and it's the difference between a prompt-helper toy and a node you can put in front of a batch sampler. StrataT8Structured is the pack's answer: you hand it a schema, it hands you back a document that was checked against that schema before you ever saw it.

What it's for

Two jobs, really. The obvious one is turning a story or a scene description into a shot list - the default schema asks for an array of shots, each with subject, action, scene, camera, duration and prompt. The second is quieter: any time you want an LLM to produce something a machine consumes, a schema is what makes it safe. No more "well, it usually writes 'Shot 1:' before the JSON".

How it works, which is the good part

Four layers, and they happen in a specific order:

  1. The schema is parsed and checked before the model is contacted. Bad schema, immediate error - you don't wait two minutes for a load to find out you left a brace off. Root must be type: "object"; Draft 4, 7, 2019-09 and 2020-12 are all accepted (no $schema means 2020-12); references must be local to the same schema. Mixed legacy dependencies with anchors are unsupported - use a JSON Pointer reference.
  2. The request is sent with a structured-output response format, so the engine is told to produce that shape.
  3. The answer is parsed with a strict parser. Duplicate keys are rejected rather than last-one-wins, non-finite numbers are rejected.
  4. It's validated. Fail, and if you gave it room, it retries.

That last bit is repair_attempts (0–2). Each retry appends "Return valid JSON only, matching every required field and its type." to the first message and asks again. Set it to 1 for unattended runs; the failure is otherwise loud - "Model output is not valid JSON matching the schema" - which is much better than a silent crash three nodes later.

Inputs worth touching

  • connection - from StrataT8Connection.
  • prompt - the story or instruction.
  • schema - the JSON Schema as text (the widget is multiline and pre-filled with the storyboard schema). Delete it and you get the storyboard default back, so don't clear it expecting "no schema".
  • system - defaults to the storyboard instruction. This is where you'd rewrite the brief if you're generating a different kind of document.
  • repair_attempts - 0–2.
  • Sampling: max_tokens (default 1024), temperature, top_p, top_k, seed, reasoning_effort, refresh.

Outputs, and which one to grab

  • json - the validated document as text. Save it, log it, or feed it to Extract.
  • shot_prompts - a native STRING list, one entry per shot's prompt field. Downstream nodes execute once per item, which is how you get one sampler run per shot without looping. It only fills for outputs that actually have a shots array of objects with a string prompt - a custom schema without that shape gives you an empty list, so use Extract instead.
  • text_list - the same prompts as a single STRATA_TEXT_LIST object, which is what you feed to StrataT8Batch when you'd rather have one node process the whole list.
  • usage_json - token accounting, and the first place to look when output gets truncated.

Install

Manager → search Strata-T8 (strata-t8, publisher t8star), or:

cd ComfyUI/custom_nodes
git clone https://github.com/T8mars/Comfyui-Strata-T8.git
python -m pip install -r Comfyui-Strata-T8/requirements.txt

jsonschema is the entire dependency list, and this is the node that uses it. Restart, save a profile in the Strata-T8 sidebar, point Connection at it. The engine, its Python/CUDA stack and the model data live in the separate portable runtime - the pack itself downloads nothing.

Where people get burned

Truncation reads like a schema failure. The default max_tokens is 1024. A three-shot storyboard with six fields per shot, plus a reasoning model's scratch work, can chew through that and stop mid-object - which then fails validation and looks like the model "can't follow the schema". Raise max_tokens before you start blaming the schema.

Non-object roots are rejected on purpose. The engine's protocol requires a schema root of type: "object", so a bare {"type":"array"} won't fly. Wrap it: an object with an array field.

Schemas with remote references won't fetch anything. HTTP and file $ref lookups are disabled outright - a workflow-supplied schema can't make the pack dial out. Keep references to #/... pointers inside the document.

additionalProperties: false is doing you a favour, keep it. The default storyboard schema uses it, which means a stray extra field is an error rather than something leaking into a prompt.

And refresh still governs re-runs. Same inputs, same refresh value, and ComfyUI serves the cached answer. Since a structured run is the expensive kind of call, that's usually what you want - bump it when you're deliberately re-rolling.

CategoryStrata-T8

Inputs (12)

NameTypeDefaultDescription
connectionSTRATA_CONNECTION—
promptSTRING—
schemaSTRING{"type": "object", "required": ["shots"], "additionalProperties": false, "properties": {"shots": {"type": "array", "minItems": 1, "maxItems": 64, "items": {"type": "object", "required": ["subject", "action", "scene", "camera", "duration", "prompt"], "additionalProperties": false, "properties": {"subject": {"type": "string", "minLength": 1}, "action": {"type": "string", "minLength": 1}, "scene": {"type": "string", "minLength": 1}, "camera": {"type": "string", "minLength": 1}, "prompt": {"type": "string", "minLength": 1}, "duration": {"type": "number", "minimum": 0.1, "maximum": 600}}}}}}—
systemSTRINGConvert the story into concrete sequential shots. Each prompt describes one visible shot. Return the requested JSON.—
repair_attemptsINT00–2—
max_tokensINT10241–131072—
temperatureFLOAT0.700–2—
top_pFLOAT0.950.01–1—
top_kINT201–64—
seedINT00–2147483647—
reasoning_effortCOMBO5 options: none, low, medium, high, xhigh
refreshINT00–2147483647—

Outputs (4)

NameTypeDescription
jsonSTRING—
shot_promptsSTRING—
text_listSTRATA_TEXT_LIST—
usage_jsonSTRING—