# Start here
Thirty-odd files in this folder is a lot of doors. This page says which one to
open. Every graph comes in two flavours: `name.json` loads in the ComfyUI
editor, `name_api.json` is the same graph in API form for scripts and
coding agents.
The folder has three tiers:
| tier | where | what it means |
|---|---|---|
| **start here** and **specialised** | this folder | measured, maintained, dials documented in [`../TUNING.md`](../TUNING.md) |
| **experimental** | [`experimental/`](experimental/), [`wan22/`](wan22/) | runs, interesting, one machine, interface may change; [`../ALPHA.md`](../ALPHA.md) says how alpha each one is |
| **archived** | [`archive/`](archive/) | superseded recipes, kept so the numbers in old write-ups still resolve; do not start from these |
## Which graph
| you want | graph | needs |
|---|---|---|
| **a long clip, short renders** | [`motion_pipeline_extend_api.json`](motion_pipeline_extend_api.json) | alpha, API form; 141-frame segments chained by writing the last 39 frames into the next segment's latent under a per-token mask. Below |
| **the normal starting point** | [`motion_pipeline_ref2va_audioinit.json`](motion_pipeline_ref2va_audioinit.json) | Ref2VA checkpoint, a reference image, the lightx2v turbo LoRA. 12 steps on the base model for pass 1, turbo at 6 steps for the de-rope, audio seeded. 192 frames at 1 MP in ~12 min on our card |
| best quality, time is no object | [`motion_pipeline.json`](motion_pipeline.json) | FL2VA checkpoint, first-frame image. 25 steps both passes, no turbo, the audio fixes included. The starting-point graph run this way measured 36 min against 12 |
| a 16 to 24 GB card (12 reported working in the field, just slower) | [`motion_pipeline_lowvram.json`](motion_pipeline_lowvram.json) | W4A8 checkpoint, NVFP4 text encoder, ~32 GB of system RAM. Measured on fenced 16/24/32 GB budgets, see [`../LOWVRAM.md`](../LOWVRAM.md) |
| to try prompts and seeds fast | [`motion_pipeline_fast_iterate.json`](motion_pipeline_fast_iterate.json) | 0.2 MP pass 1, 0.4 MP de-rope, ~95 s. A scouting loop, not a final |
If you only read one more line: **pass 1 decides the choreography, pass 2
repairs the bursts.** Spend steps on pass 1; pass 2 is where the turbo
LoRA belongs. The base model on pass 2 is better still, if you have
forever to spend.
## The essential graph
Every motion graph in this folder is this chain with something bolted on.
Eleven nodes, two of them samplers:
```mermaid
flowchart TD
subgraph P1["pass 1: the baseline (decides the choreography)"]
I2V["MiniMaxH3ImageToVideo
or ReferenceToVideo"] --> S1["SamplerCustomAdvanced
(12 to 25 steps, base model)"]
S1 --> D1["VAEDecode + VAEDecodeAudio"]
end
subgraph DR["the de-rope (repairs the bursts)"]
S1 -- "latent" --> O["H3 Jerk Oracle
(where is motion too fast)"]
O -- "hold_map" --> TS["H3 Time Smear
(hold frames where it is)"]
D1 -- "frames" --> TS
D1 -- "audio" --> AS["H3 Audio Smear
(same clock, for the audio)"]
TS --> E["VAEEncode"]
E --> V2V["H3 V2V Init
(video + audio latent)"]
AS --> V2V
V2V --> S2["SamplerCustomAdvanced
(H3 Inject Schedule, partial denoise)"]
S2 --> D2["VAEDecode + VAEDecodeAudio"]
D2 --> R["H3 Exact Recover
+ H3 Audio Recover
(drop the held frames)"]
end
R --> OUT["CreateVideo / SaveVideo
original length, bursts repaired"]
```
Three dials do most of the work:
| dial | node | what it trades |
|---|---|---|
| `preset` / `q` / `d_max` | H3 Jerk Oracle | how much of the clip gets slowed, and by how much. `balanced` is q 0.75, d_max 4 |
| `inject` | H3 Inject Schedule | how far pass 2 is allowed to re-decide. 0.50 is sharper and tracks the source closer, 0.70 is the safer playback default. Effective pass-2 steps = total_steps x inject |
| `audio_mode` | H3 V2V Init | `0.5` seeds pass 2 with the baseline performance so dialogue survives the slow-down |
The full symptom-to-dial table is [`../TUNING.md`](../TUNING.md#symptom-to-dial).
## Specialised graphs
Each one is the essential graph plus the nodes named in the diagram.
**You know where the problem is.**
[`motion_pipeline_targeted.json`](motion_pipeline_targeted.json) replaces
the oracle's decision with typed time ranges; you pay for your spans only.
```mermaid
flowchart LR
O["H3 Jerk Oracle"] -. "review the heatmap" .-> M["H3 Manual Hold Map
(type the ranges)"]
M -- "hold_map" --> TS["H3 Time Smear"]
```
**You want to paint it instead.**
[`motion_pipeline_editor.json`](motion_pipeline_editor.json) puts a GUI on
the hold map: blocks, painting, automation.
[`motion_pipeline_editor_segment.json`](motion_pipeline_editor_segment.json)
adds a crop around one burst so a long clip pays for the window only.
```mermaid
flowchart LR
O["H3 Jerk Oracle"] --> ED["H3 Motion Editor
(paint the envelope)"]
ED --> TS["H3 Time Smear"]
TS --> C["H3 Segment Crop
(one burst + handles)"]
C --> S2["pass 2 on the window only"]
S2 --> SP["H3 Segment Splice
(back into the full clip)"]
ED --> MC["H3 Motion Composite
(blend repaired over original)"]
```
**Cheap pass 1, expensive pass 2.**
[`motion_pipeline_upscale_derope.json`](motion_pipeline_upscale_derope.json)
renders the baseline at 0.4 MP and de-ropes at 1.5 MP: 89% of native
detail in 83% of the time on our measurements.
```mermaid
flowchart LR
D1["pass 1 frames
0.4 MP"] --> TS["H3 Time Smear"] --> SC["ImageScale
to 1.5 MP"] --> E["VAEEncode"] --> S2["pass 2 at 1.5 MP"]
```
**The dilated pass does not fit the card.**
[`motion_pipeline_rolling_window.json`](motion_pipeline_rolling_window.json)
(and the `_lowvram` twin) slides a fixed-size window across the clip, so
peak memory follows the window, not the clip. Alpha: validated end to
end, waiting on field reports from real 24 to 32 GB cards.
```mermaid
flowchart LR
TS["H3 Time Smear"] --> WP["H3 Window Plan
(cut the clip into windows)"]
WP --> S2["pass 2, one window per queue item"]
S2 --> WC["H3 Window Collect
(bank, then reassemble)"]
WC --> R["H3 Exact Recover"]
```
**Two different long-video jobs, easy to confuse.** Already have one long
clip and want it repaired? That is the rolling window above: one world,
the expensive pass chunked. Want to MAKE a long clip but can only afford
short generations? That is extension: short segments generated and
de-roped one at a time, a short video+audio tail carried into the next
segment as its opening context, the overlap trimmed at assembly. The two
trade differently: the window keeps one semantic world at bounded memory;
extension accepts some drift between separately generated worlds in
exchange for bounded compute.
**Make a long clip on a smaller card.**
[`motion_pipeline_extend_api.json`](motion_pipeline_extend_api.json) (alpha,
API form only for now) renders two 141-frame segments and assembles 243
frames. Segment 2 does not restart: segment 1's last 39 frames are written
into its own pass-1 latent and held there by a time-varying per-token mask
(the audio handle rides an audio-only `MiniMaxH3AddGuide` at frame 0), so
the shot's momentum carries across. The de-rope then holds that prefix at
1 AND freezes it in pass 2, protects the last 17 frames of any non-final
segment (a gesture that runs into the cut would come back fast after
recovery otherwise), trims the hidden overlap, colour-matches the new
material from it, and appends. The plan node prints the arithmetic
(141 = 235 audio ticks, handle 39 = 65, new 102 = 170: nothing fractional
accumulates) and which anchor the running core supports; without #15375
it falls back to the image guide. Measured on two content sets: the join
lands at 0.86x to 1.1x the clip's ordinary frame-to-frame motion (the
guide fallback measures 5x to 6.5x), and the camera's velocity is
continuous through the cut.
```mermaid
flowchart LR
R1["segment 1
recovered"] --> TC["H3 Tail Context
(last 39 frames + audio)"]
P["H3 Extension Plan
(141/39 atom)"] --> TC
TC --> ML["tail written into the
pass-1 target latent
(per-token mask)"] --> S2["segment 2 pass 1"]
TC -- "audio only" --> AG["MiniMaxH3AddGuide @ 0"] --> S2
S2 --> O["H3 Jerk Oracle"] --> PP["H3 Protect Prefix
(hold 1: prefix + last 17)"] --> TS["H3 Time Smear"]
TS -- "length" --> FM["H3 Prefix Freeze Mask"] --> V["H3 V2V Init
(time_varying)"]
V --> D2["pass 2 + recover"] --> T["H3 Trim"] --> N["H3 Seam Normalize"] --> A["ImageBatch + AudioConcat"]
```
The grid rules behind it are in [`../TUNING.md`](../TUNING.md#chained-clips-and-the-audio-clock).
**No audio init.**
[`motion_pipeline_ref2va.json`](motion_pipeline_ref2va.json) is the
starting-point graph without `H3 Audio Smear`; use it to hear what the
audio init changes, otherwise prefer the `_audioinit` twin.
**Contact sheets** are a different product: one call, several consistent
views of a character.
[`contact_sheet.json`](contact_sheet.json) (from a reference image) and
[`contact_sheet_t2i.json`](contact_sheet_t2i.json) (from text).
```mermaid
flowchart LR
R["LoadImage (optional)"] --> CS["H3 Contact Sheet
(conditioning + latent)"] --> S["SamplerCustomAdvanced"] --> CD["H3 Contact Sheet Decode"] --> SI["SaveImage x views"]
```
## Experimental
In [`experimental/`](experimental/):
- `motion_pipeline_adapter.json`: the motion adapter pilot, a LoRA trained
on the de-rope task, on the pass-2 model only. Known costs in the README
section [The motion adapter (pilot)](../README.md#the-motion-adapter-pilot).
- `motion_window_pinned_adapter_api.json`: a clip you already have,
regenerated at denoise 0.70 with first and last frames pinned, adapter on.
- `time_burst_api.json`: a look, not a repair, and it breaks things on
purpose. The windowed insert with the in-between tokens born as pure
noise: no crossfade init, no adapter, no guide. Inside the window the
model has no clock, so it spends the free slots on motion: the span runs
at about 2.7x the source speed, a burst inside an otherwise normal shot,
with flares it invents along the way. This is the exact graph (same seed,
same hold map) that made [`../assets/time_burst_result.mp4`](../assets/time_burst_result.mp4)
from [`../assets/time_burst_plate.mp4`](../assets/time_burst_plate.mp4);
copy the plate into `ComfyUI/input/` and you can watch it work before
pointing it at your own clip. Dials: the hold map (more holds, longer and
wilder burst), `H3InjectSchedule` inject (1.0 is the burst; switch
`H3TemporalInsert` to lerp init at 0.4 to 0.6 and it calms toward the
ordinary insert), and where you draw the window. One clip, one seed, our
card; expect it to be able to make things worse.
In [`wan22/`](wan22/): the de-rope on a model that is not H3. One cell
measured so far; the dials are not tuned there.
## Two recipes, and why both exist
The graphs in this folder were minted in two waves, and the settings
differ. Neither is wrong; they are different budgets.
| | the August 8 recipe | the August 19 recipe |
|---|---|---|
| graphs | `motion_pipeline`, `_targeted`, `_editor`, `_editor_segment` | `_ref2va_audioinit`, `_ref2va`, `_fast_iterate`, `_upscale_derope`, `_rolling_window`, `_lowvram` |
| pass 1 | 25 steps, `simple`, `res_multistep` | 12 steps, `linear_quadratic`, `gradient_estimation` |
| pass 2 | base model, inject 0.70 | turbo LoRA, 6-step `beta`, inject 0.70 (or 0.48 on the window graphs) |
| audio | seeded (`H3 Audio Smear`) in all of them | seeded |
| cost | ~3.5x one baseline render | ~1x to 1.3x |
One thing we learned the hard way: the turbo LoRA dropped into the August 8
graph, with its sampler and schedule unchanged, renders jerky and
pixelated. Turbo on pass 2 needs the whole August 19 recipe, not just the
LoRA. If you want turbo, start from a graph that already has it.
## When it fails
| symptom | first thing to check |
|---|---|
| dialogue or audio sounds wrong, words mangled | update ComfyUI; the H3 tokenizer special-token fix landed upstream 2026-08-22 (PR #15808), and an older core corrupts H3 prompts before any node here runs |
| the reference stops influencing pass 2 | put `BasicScheduler` / stock sigmas back before debugging anything else; one field report traced exactly this to a third-party scheduler |
| pass 2 looks jerky and pixelated | turbo LoRA in an August 8 graph, see above |
| the de-rope OOMs | [`../HARDWARE.md`](../HARDWARE.md), then [`../LOWVRAM.md`](../LOWVRAM.md) |
| VAE encode takes minutes | it is the slowest stage on a small card; `H3 Free Cache` before it, `H3 Evict Text Encoder` after the prompt. The TAE encoder (125x faster) needs a ComfyUI newer than 2026-08-17 (core PR #15695) |
| the motion got slower, not cleaner | `inject` too high or `d_max` too high; try `faithful detail 0.50` |
Anything else: [`../TUNING.md`](../TUNING.md) is written for humans and for
the coding agent working on your behalf. Paste a graph and a symptom into
either and you will usually get the dial.