--- license: mit tags: - comfyui - comfyui-nodes - custom-nodes - video - video-generation - text-to-video - image-to-video - minimax-h3 --- # Hand Tie Clips One node. Write a shot plan, drop in your reference stills, queue. ![Six consecutive frames across a join](https://media.githubusercontent.com/media/dntpi/ComfyUI-Hand-Tie-Clips/main/docs/img/seam-frames.png) *Six consecutive frames spanning the join between hop 1 and hop 2. One of these is the last frame the first generation produced and the next is the first frame of a second, separate generation. The pack exists so that you cannot tell which.* > **Renamed 2026-08-29.** This pack was `ComfyUI-H3-Ref-Chain`. The nodes now > live under the **Hand Tie Clips** category and register as `HandTieClips`, > `HTCChainPreview`, `HTCToneCompensate` and `HTCContinuityState`. The old ids > are still registered as deprecated aliases, so **every workflow saved before > the rename keeps loading** — they are just hidden from node search. Nothing > needs migrating. > **2.0.0 — 2026-09-05.** Full release. One continuous take every hop can > lip-sync to (`master_audio_file`, empty = off). An opt-in last-frame > AddGuide (`last_frame_guide`) pins `start_image` at a hop's last pixel; > default `off`, recommended `before_restart` (only the hop before an > `anchor: restart`, so the cut meets on one image). `still` plants it on > every hop and fights an authored `framing`. `anchor: "restart"` is a > chain start and now writes its full length instead of dropping 0.9 s of > new content. A shot can name which stills ride it (`refs`); omitted is > the register default, `[]` is none. `tone_anchor_ref=still` holds the > photograph rather than hop 1, which already missed it. Three > reference-clip slots, three voice slots, `pin_mech`, and a hop cache > that no longer pickles. New widgets were appended, so saved 1.1 graphs > keep their values. What a GPU has not confirmed yet is named in > [`CHANGELOG.md`](CHANGELOG.md). > **0.4.1 — 2026-08-30.** The 0.4.0 feature set was built without a browser or a > GPU and verified offline only. It has now been run in ComfyUI, and two things > were broken: the five new dials were never added to the run panel's widget list > (they worked, but rendered as raw dials on the node body), and a dry run > returned a 1×1 placeholder image that **libx264 cannot encode** — so every dry > run wired to `SaveVideo`, which is what the Starter ships, died in > `avcodec_open2`. Both fixed. The Starter now also ships the seam report wired. > Measurements are in [`docs/DEVLOG.md`](docs/DEVLOG.md) section 21. > **0.4.4 — 2026-08-30.** Two local models were given `prompt_pack/SYSTEM_PROMPT.md` > and the same scene, and both made the same two mistakes — so both were the > prompt's fault, not theirs. The register example had no place tag in it, so > each model invented its own convention (`kitchen_plate`) while leaving > `@kitchen` in the beat, and the run stopped on an unknown reference. One model > also wrote `"name": "@cook_face"` into `subjects`, which parsed, rendered, and > quietly put a literal at-sign in front of the text encoder on every > continuation hop. The prompt now shows a place tag on both sides of the round > trip and says the two spellings are one string; `refs.py` now rejects an > `@tag` in `name`, `locked` or `context` instead of encoding it. The RUN panel > also has its tooltips back — it read them from `widget.options`, where this > frontend does not keep them. Section 22 of the devlog has the A/B. > **0.4.5 — 2026-08-30.** The hop cache no longer needs `ffmpeg` on PATH. It > used to shell out to an ffmpeg binary to write its lossless FFV1, so the > feature that makes a tone A/B cost 14 seconds instead of 164 raised a > `RuntimeError` for anyone who did not happen to have ffmpeg installed — > which ComfyUI itself never requires. It now encodes in process through PyAV, > which ComfyUI already depends on. **The format is unchanged** (ffv1 / > `rgb48le` / level 3), verified bit-exact in both directions, so caches > written by the old path still read and a resumed chain still matches an > uninterrupted one. This also clears the Comfy registry's security scan, which > flags any spawn of an external command from a custom node regardless of how > it is invoked. Section 23 of the devlog. > **1.0.0 — 2026-09-02.** First full release. The headline is **WRITE**: a plan > writer on the node itself, pointed at any OpenAI-compatible server, that fills > the script and the reference rows together and sends your reference pictures > with the request. Around it, the parts that make a written plan survive > contact with the model — the schema the server is handed now *requires* both > documents, so a reply carrying only half of one stopped being a silent > failure; the reference rail owns each picture's pixel budget, which a plan > used to reset to full and quietly triple the load against a fixed canvas; and > the writer is told the hop length, so beats are sized to the clip instead of > to a guess. Three plan lints were measured against real renders and found to > be warning about correct work — a restated framing read as a cut, a > single-room chain read as an abandoned location — and were narrowed. Rule 3 > of the prompt pack grew the case that cost the most renders: a hop that > speaks *later* has opening seconds with a picture and no sound assigned, and > the model fills them with dialogue nobody wrote. Ending the previous hop > quiet buys a quiet pin, not a quiet opening. Sections 31 and 32 of the devlog > have the measurements. > **1.1.1 — 2026-09-05.** Fixes a crash on hop 1 for anyone whose ComfyUI > orders `MiniMaxH3ReferenceToVideo`'s parameters differently from the build > this was written against — reported as `got multiple values for argument > 'ref_image_size'`, with nothing sampled and nothing written. The pack was > passing Core's first seven arguments positionally; it now passes every > argument by name at all three Core call sites, so a reordering upstream > cannot rebind anything. If a future Core changes the parameter *names*, the > pack now says which node, which arguments it passed and which the installed > Core takes, instead of raising a bare `TypeError`. No behaviour changes. > > **1.1.0 — 2026-09-03.** The panel is a 4:3 box with tabs instead of one long > scrolling column, and RUN stays pinned at the bottom. The **WRITE** draft is > readable — it used to clip every beat at 110 characters and throw away the > duration, seed, directives and per-shot references before rendering, so what > you were asked to Accept was a row of sentences ending in an ellipsis — and it > now survives leaving the tab or reloading the page. Shot cards carry `⏵` and > `lock` buttons driving `render_from` / `render_through`, the new one being the > other end of a range `render_through` has had since 0.4: everything before the > start is replayed from the hop cache rather than re-rendered. > > The bug worth upgrading for: **a reference pinned to any hop but the first > tended to be rendered as the shot.** `retention_analysis:` — the text that > tells the encoder what a picture is *for* — was emitted on hop 1 only, so a > still scheduled onto hop 3 arrived uncited; and the identity lock never read > `retention`, so a wardrobe plate carrying a subject was announced as *"the > only identity … that face, bone structure, and hairstyle match the photograph > exactly"* about a photograph of an apron, while the closer simultaneously said > clothing follows the live frame. Both fixed. The reference *clip* had the same > gap — it went in as `