docs: hires routing table everywhere (hires_factor = routing switch); PREVIEW-labeled SaveVideo; routing-framed tooltip; refreshed v1.5 zip
Browse files- ComfyUI_JoyAI_Echo_v1.5_COMPLETE.zip +2 -2
- README.md +315 -309
- nodes.py +11 -7
- workflow/JoyEcho_Multishot_Workflow_PUBLIC.json +354 -343
ComfyUI_JoyAI_Echo_v1.5_COMPLETE.zip
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cbb87dac03ddc9b22665642794e996bdf2b7deec88d73cc8f1115b037159cd5b
|
| 3 |
+
size 180737
|
README.md
CHANGED
|
@@ -1,309 +1,315 @@
|
|
| 1 |
-
---
|
| 2 |
-
license: other
|
| 3 |
-
license_name: ltx-2-community-license
|
| 4 |
-
license_link: https://huggingface.co/Lightricks/LTX-2/blob/main/LICENSE.txt
|
| 5 |
-
tags:
|
| 6 |
-
- comfyui
|
| 7 |
-
- joyai-echo
|
| 8 |
-
- ltx-video
|
| 9 |
-
- multishot
|
| 10 |
-
- patch
|
| 11 |
-
---
|
| 12 |
-
|
| 13 |
-
# JoyAI-Echo GGUF nodes — multishot fixes + automation patch
|
| 14 |
-
|
| 15 |
-
A set of bug fixes and features layered on top of the community
|
| 16 |
-
`ComfyUI_JoyAI_Echo_GGUF_Nodes` pack (the Rebels GGUF loader stack around
|
| 17 |
-
JoyAI-Echo). Everything here targets the **multi-shot** path (`JoyEcho_Generate`
|
| 18 |
-
+ the discrete Rebels loaders / `JoyEcho_ModelLoader`).
|
| 19 |
-
|
| 20 |
-
This is a **patch drop**, not a standalone pack: copy these files over a working
|
| 21 |
-
install of the same pack (back up first). The files are interdependent — in
|
| 22 |
-
particular `nodes.py` calls new signatures added to the two `libs/` files, so
|
| 23 |
-
apply them together.
|
| 24 |
-
|
| 25 |
-
Tested on an RTX 5090 (32 GB) and a 3090 (24 GB), ComfyUI 0.26–0.27,
|
| 26 |
-
torch 2.8–2.11, with the JoyAI-Echo bf16 release and self-built Q8 GGUFs.
|
| 27 |
-
|
| 28 |
-
---
|
| 29 |
-
|
| 30 |
-
## Files in this package
|
| 31 |
-
|
| 32 |
-
```
|
| 33 |
-
nodes.py # JoyEcho_TextEncode / _Generate / _ModelLoader / _LLMEnhance
|
| 34 |
-
__init__.py # registrations for the new nodes
|
| 35 |
-
rebels_loaders.py # discrete GGUF loaders (text-encoder fixes)
|
| 36 |
-
joyecho_prompt_source.py (new node) # one dropdown: .txt briefs + .json scripts
|
| 37 |
-
joyecho_ref_picker.py (new node) # auto reference-image picker by character name
|
| 38 |
-
joyecho_ref_batch.py (new node) # None-tolerant image batcher
|
| 39 |
-
joyecho_script_picker.py (new node) # JSON dropdown (superseded by PromptSource)
|
| 40 |
-
libs/ltx_distillation/models/ltx_wrapper.py # fp8 quantization passthrough
|
| 41 |
-
libs/ltx_core/loader/fuse_loras.py # kohya-LoRA fusion + alpha scaling + fuse telemetry
|
| 42 |
-
libs/ltx_core/quantization/policy.py # fp8_scaled_mm_torch policy (+ sm_89 gate)
|
| 43 |
-
libs/ltx_core/quantization/fp8_torch_mm.py # native-fp8 Linear forward (torch._scaled_mm)
|
| 44 |
-
libs/ltx_distillation/utils.py # tiled VAE decode
|
| 45 |
-
libs/ltx_distillation/inference/memory_multishot.py # memory bank TRIM FIX (critical)
|
| 46 |
-
libs/ltx_distillation/inference/bidirectional_pipeline.py # dtype hardening vs fp8 params
|
| 47 |
-
libs/ltx_distillation/inference/memory_bidirectional_pipeline.py # dtype hardening vs fp8 params
|
| 48 |
-
prompts/long_story_writer_system_prompt.md # (optional) de-musicked + character-age edits
|
| 49 |
-
```
|
| 50 |
-
|
| 51 |
-
The files are interdependent - apply the whole set together, never cherry-pick
|
| 52 |
-
(a nodes.py newer than its libs/ raises AttributeError at load).
|
| 53 |
-
|
| 54 |
-
---
|
| 55 |
-
|
| 56 |
-
## Bug fixes
|
| 57 |
-
|
| 58 |
-
### 1. `enable_audio_memory=False` silently disabled ALL cross-shot memory
|
| 59 |
-
The pack computed `audio_memory_latent=None` when audio memory was off, and the
|
| 60 |
-
video **memory-bank save was gated on that latent being non-None** — so with
|
| 61 |
-
audio memory off (the standard anti-drone setting) the bank never filled and
|
| 62 |
-
cross-shot **identity** silently died (symptom: `memory_size=0` every shot even
|
| 63 |
-
with `memory_max_size=7`; a new face each shot).
|
| 64 |
-
Fix: memory storage is now unconditional; `enable_audio_memory` gates only the
|
| 65 |
-
audio-memory **injection** path. Verify: console `memory_size=` should climb
|
| 66 |
-
0,1,2,… capped at your `memory_max_size`. (`nodes.py`)
|
| 67 |
-
|
| 68 |
-
### 1b. Memory bank trim was a NO-OP whenever `memory_max_size <= num_fix_frames` (CRITICAL)
|
| 69 |
-
`PairedAudioVideoMemoryBank._trim()` computed `tail[-keep_tail:]` - and when
|
| 70 |
-
`keep_tail == 0` (e.g. the common max_size=3 / num_fix_frames=3 combo),
|
| 71 |
-
`tail[-0:]` is the WHOLE list, so the bank grew unbounded: every shot
|
| 72 |
-
conditioned on EVERY prior shot. Symptom: console `memory_size=` climbing
|
| 73 |
-
0,1,2,...,N-1 past your cap, and severe compounding quality degradation over
|
| 74 |
-
long runs (waxy skin, contrast crush, smearing by the late shots - the "gets
|
| 75 |
-
worse as it goes" failure). Fixed with a proper zero-tail branch + anchor
|
| 76 |
-
clamp; `memory_size=` now freezes at your cap. This one fix eliminated the entire
|
| 77 |
-
long-run degradation in our tests. (`libs/.../memory_multishot.py`)
|
| 78 |
-
|
| 79 |
-
### 2. GGUF text-encoder loader (`RebelsJE_TextEncoder`)
|
| 80 |
-
Two fixes so a text-only Gemma-3 GGUF loads cleanly:
|
| 81 |
-
- **meta-strip**: drop `vision_tower` / `multi_modal_projector` / `lm_head`
|
| 82 |
-
(the text-only GGUF has no weights for them → "Cannot copy out of meta tensor").
|
| 83 |
-
- **device-unify**: pin the embeddings-processor to the encoder's actual device
|
| 84 |
-
(GGUF Gemma runs on CPU while the connector was on cuda → addmm device mismatch).
|
| 85 |
-
- **fp8 gemma scale-key layouts**: the `our_fp8` swap only recognized its own
|
| 86 |
-
export layout (bare module names + `.scale_weight`); standard HF/comfy-style
|
| 87 |
-
fp8 gemma files (`<module>.weight` + `.weight_scale`, e.g. community
|
| 88 |
-
abliterated builds) silently loaded with **zero modules swapped** — the
|
| 89 |
-
encoder stayed bf16 with no indication. Both layouts are now accepted
|
| 90 |
-
(per-tensor scalar scales; per-channel scales are skipped and those modules
|
| 91 |
-
stay bf16), and a loud warning prints if a file matches neither.
|
| 92 |
-
(`rebels_loaders.py`)
|
| 93 |
-
|
| 94 |
-
---
|
| 95 |
-
|
| 96 |
-
## Features
|
| 97 |
-
|
| 98 |
-
### 3. Split per-domain negative lever (`JoyEcho_TextEncode`)
|
| 99 |
-
The DMD pipeline has no CFG, so the only steering lever is embedding-space.
|
| 100 |
-
Instead of one `negative_prompt`/`negative_scale` that steers both branches,
|
| 101 |
-
this splits it:
|
| 102 |
-
- `negative_prompt_video` / `negative_scale_video` — kills burned-in
|
| 103 |
-
captions/subtitles. Working value ~0.5. **Above ~0.8 it over-rotates the
|
| 104 |
-
video context and locks every shot to shot 1's composition** (scene-lock).
|
| 105 |
-
- `negative_prompt_audio` / `negative_scale_audio` — kills invented
|
| 106 |
-
music/score. Keep ≤ ~0.4 or dialogue suffers.
|
| 107 |
-
Steering is norm-preserving (RescaleCFG-style): `cond' = renorm(cond + s*(cond − neg))`.
|
| 108 |
-
Old single-widget names still work as a fallback. (`nodes.py`)
|
| 109 |
-
|
| 110 |
-
### 4. Passthrough mode (`JoyEcho_LLMEnhance`)
|
| 111 |
-
`mode = "passthrough (raw JSON, skip LLM)"` — feed a finished
|
| 112 |
-
`{"prompts":[...]}` script straight through with no LLM call / no API key.
|
| 113 |
-
Auto-detects when `story_idea` already parses as that JSON. (`nodes.py`)
|
| 114 |
-
|
| 115 |
-
### 5. Reference-image conditioning — I2V-as-reference (`JoyEcho_Generate`)
|
| 116 |
-
New `reference_image` (IMAGE batch, up to 4). Identity references are prepended
|
| 117 |
-
as **video-only conditioning clips** at the memory-encode step — they are
|
| 118 |
-
**never** written into the paired audio/video bank. (An earlier attempt that
|
| 119 |
-
seeded refs into the bank with zero-filled audio latents injected loud
|
| 120 |
-
background noise with 2+ refs; video-only conditioning avoids it entirely.)
|
| 121 |
-
Also new: `head_trim_frames` (auto 8 with refs) drops the first N frames of each
|
| 122 |
-
shot, where the model morphs out of the reference/memory content. The trim is
|
| 123 |
-
applied once right after decode, so the final output, the per-shot preview
|
| 124 |
-
files, and any external concat of them stay frame-identical. (`nodes.py`)
|
| 125 |
-
|
| 126 |
-
### 6. Shot transitions (`JoyEcho_Generate`)
|
| 127 |
-
`transition`: `cut` (original) / `dissolve` (overlap cross-dissolve + equal-power
|
| 128 |
-
audio crossfade) / `vhs_glitch` (analog static burst at each boundary: snow,
|
| 129 |
-
tear bands, dropout lines + a raised-cosine tape-noise audio bed).
|
| 130 |
-
`transition_frames`, `glitch_intensity` tune it. (`nodes.py`)
|
| 131 |
-
|
| 132 |
-
### 7. fp8 transformer quantization (`JoyEcho_ModelLoader`)
|
| 133 |
-
New `fp8_transformer` toggle. Quantizes the DiT's attention/FF linear weights to
|
| 134 |
-
`float8_e4m3fn` **at load, from the normal bf16 checkpoint** (uses the vendored
|
| 135 |
-
`ltx_core.quantization.QuantizationPolicy.fp8_cast()` — upcasts per-layer at
|
| 136 |
-
inference). Roughly halves DiT weight memory and halves sequential-offload PCIe
|
| 137 |
-
traffic; keeps memory training + all tensors; VAEs/text-encoder/non-linears stay
|
| 138 |
-
bf16. Ignored when a GGUF DiT is selected (already quantized).
|
| 139 |
-
(`nodes.py` + `libs/ltx_distillation/models/ltx_wrapper.py` — new `quantization`
|
| 140 |
-
param; the quantized build path skips the post-load dtype cast that would
|
| 141 |
-
otherwise silently upcast fp8 back to bf16.)
|
| 142 |
-
|
| 143 |
-
### 8. Tiled VAE decode (`JoyEcho_Generate`)
|
| 144 |
-
Decoding a long high-res shot (e.g. 241f @ 1280×736) in one pass hard-aborts the
|
| 145 |
-
VAE decode on a 24–32 GB card (fatal cuDNN abort mid-conv, not a catchable OOM).
|
| 146 |
-
New `decode_tiling` (`auto`/`on`/`off`) routes decode through the vendored
|
| 147 |
-
`VideoDecoder.tiled_decode` — **temporal-only** 64-frame chunks with 24-frame
|
| 148 |
-
blended overlap (no spatial tiles → no spatial seams), streaming each chunk to
|
| 149 |
-
CPU. `auto` engages only above a size threshold, so small renders keep the
|
| 150 |
-
original single-pass decode bit-for-bit.
|
| 151 |
-
(`nodes.py` + `libs/ltx_distillation/utils.py` — `decode_benchmark_sample` gains
|
| 152 |
-
a `video_tiling_config` kwarg + `_decode_video_tiled_uint8`.)
|
| 153 |
-
|
| 154 |
-
### 9. Model dropdown (`JoyEcho_ModelLoader`)
|
| 155 |
-
New `model_file` combo lists every `.safetensors` / `.gguf` under the ComfyUI
|
| 156 |
-
`checkpoints` / `diffusion_models` / `unet` dirs. Pick a `.safetensors` → full
|
| 157 |
-
checkpoint (replaces `checkpoint_path`); pick a `.gguf` → DiT loaded from GGUF
|
| 158 |
-
while `checkpoint_path` still supplies the VAEs / vocoder / text connectors.
|
| 159 |
-
`"(use checkpoint_path)"` keeps the old typed-path behavior. A matching
|
| 160 |
-
`lora_file` dropdown lists every `.safetensors` under `models/loras`
|
| 161 |
-
(applied at `lora_strength` on the safetensors DiT path; ignored for GGUF). Plus a clear
|
| 162 |
-
early error if `gemma_path` is a `.gguf`/file/sidecar-less dir (this loader
|
| 163 |
-
needs the HF `gemma-3-12b-it` folder; GGUF Gemma only works via
|
| 164 |
-
`RebelsJE_TextEncoder`). (`nodes.py`)
|
| 165 |
-
|
| 166 |
-
### 10. LoRA loading hardening (`JoyEcho_ModelLoader` + `libs/.../fuse_loras.py`)
|
| 167 |
-
- A `lora_file` dropdown picks LoRAs from `models/loras` (existing
|
| 168 |
-
`lora_strength` widget applies).
|
| 169 |
-
- Fusion now supports **kohya naming** (`lora_down`/`lora_up`) in addition to
|
| 170 |
-
PEFT (`lora_A`/`lora_B`), with standard `alpha/rank` scaling — previously a
|
| 171 |
-
kohya-named LoRA silently did NOTHING (zero keys matched, no warning).
|
| 172 |
-
- Fusion prints how many weights fused, and WARNS LOUDLY when a provided LoRA
|
| 173 |
-
matched zero keys.
|
| 174 |
-
- The loader refuses **ComfyUI-quantized checkpoints** (`.comfy_quant` marker
|
| 175 |
-
tensors, e.g. "fp8mixed learned" builds) with a clear error: this loader
|
| 176 |
-
never applies their weight scales (the model would silently load mis-scaled)
|
| 177 |
-
and LoRA fusion on them crashes with shape errors. Use bf16 checkpoints.
|
| 178 |
-
|
| 179 |
-
### 11. Automation / batching nodes (new)
|
| 180 |
-
- **`JoyEcho_PromptSource`** — one dropdown listing LPFF-style `.txt` briefs
|
| 181 |
-
(from the inspire-pack prompts tree) **and** passthrough `.json` scripts
|
| 182 |
-
(`input/joyecho_prompts/`). Multi-block briefs fan out like
|
| 183 |
-
LoadPromptsFromFile. Emits `story_idea` (→ LLMEnhance) + `character`
|
| 184 |
-
(→ RefPicker) + `count`. Replaces the LPFF→UnzipPrompt chain and lets you
|
| 185 |
-
switch prompt sources with one dropdown instead of rewiring.
|
| 186 |
-
- **`JoyEcho_RefPicker`** — auto-selects a character reference image from a
|
| 187 |
-
folder tree keyed by character name (a `character_pick` dropdown of the
|
| 188 |
-
folder names, a typed/wired `character` string, or a prompt scan — dialogue
|
| 189 |
-
mentions are stripped so only the on-screen subject wins). The dropdown
|
| 190 |
-
survives model refreshes, an explicitly named character that matches no
|
| 191 |
-
folder refuses to fall back to the prompt scan (a wiped/typo'd name can't
|
| 192 |
-
silently become the wrong character's face), and the cache signature
|
| 193 |
-
includes the prompt text (without it, ComfyUI could serve a cached pick
|
| 194 |
-
from a previous queue item). `on_no_match=no_reference` returns nothing so
|
| 195 |
-
a batch keeps running.
|
| 196 |
-
- **`JoyEcho_RefBatch`** — None-tolerant image batcher: combines up to 4
|
| 197 |
-
optional IMAGE inputs (e.g. two RefPickers for a two-character shot), skips
|
| 198 |
-
missing refs, resizes mismatched sizes to the first image, outputs `None` if
|
| 199 |
-
all are missing (Generate then just skips identity seeding). The stock KJNodes
|
| 200 |
-
`ImageBatchMulti` crashes with `'NoneType' has no attribute 'shape'` on a
|
| 201 |
-
missing ref; this replaces it.
|
| 202 |
-
- **`JoyEcho_ScriptPicker`** — JSON dropdown (superseded by PromptSource; kept
|
| 203 |
-
for compatibility).
|
| 204 |
-
|
| 205 |
-
### 12. GPU encode hot-swap (`JoyEcho_TextEncode`)
|
| 206 |
-
With `low_vram` the Gemma encoder used to encode every shot on CPU (~10s+ per
|
| 207 |
-
shot). The encode pass now borrows the (idle) GPU when the encoder fits free
|
| 208 |
-
VRAM - with a fits-check, an OOM fallback to CPU, and a move-back before the
|
| 209 |
-
denoise phase. 20-shot encodes drop from minutes to seconds. (`nodes.py`)
|
| 210 |
-
|
| 211 |
-
### 13. `encoder_fp8` (`JoyEcho_ModelLoader`)
|
| 212 |
-
Stores the Gemma encoder's linear weights as float8_e4m3fn with per-layer
|
| 213 |
-
upcast at encode (encode runs once per item, so the upcast tax that makes
|
| 214 |
-
fp8 slow on the DiT is irrelevant here). Wrapper drops ~24GB -> ~21GB and the
|
| 215 |
-
GPU hot-swap engages on 32GB cards; JD's connector projections stay bf16.
|
| 216 |
-
|
| 217 |
-
### 14. `fp8_scaled_mm` (`JoyEcho_ModelLoader`) - native fp8 compute
|
| 218 |
-
Stores the DiT's attention/FF linears as fp8 AND runs the matmuls natively
|
| 219 |
-
via `torch._scaled_mm` - no per-layer upcast tax (measured x2.8 raw kernel /
|
| 220 |
-
x1.5 end-to-end vs bf16 on an RTX 5090). ~22GB resident enables
|
| 221 |
-
`sequential_offload=False` at moderate resolutions. REQUIREMENTS: sm_89+
|
| 222 |
-
GPU (RTX 40/50 - clear error on older cards, with a per-device runtime
|
| 223 |
-
fallback to upcast), and a **bf16 source checkpoint** (an fp8 FILE would load
|
| 224 |
-
every tensor fp8 with the cast skipped and crash the noise path - guarded
|
| 225 |
-
with a clear error). Tensorwise dynamic activation quant: A/B your content
|
| 226 |
-
before adopting.
|
| 227 |
-
|
| 228 |
-
### 15. `resident_blocks` (`JoyEcho_Generate`)
|
| 229 |
-
Sequential offload middle ground: pin the first N of 48 transformer blocks
|
| 230 |
-
permanently on GPU, stream the rest. N=24 halves the per-step PCIe traffic;
|
| 231 |
-
raise until VRAM is nearly full. Composes with fp8 modes (fp8 blocks are
|
| 232 |
-
half the bytes both resident and streamed).
|
| 233 |
-
|
| 234 |
-
### 16. Hires-fix second pass (`JoyEcho_Generate`)
|
| 235 |
-
`hires_factor` (>1.0) + `hires_denoise`: after all shots render, each shot is
|
| 236 |
-
bicubic-upscaled, VAE re-encoded, re-noised at a tail sigma and re-denoised
|
| 237 |
-
through the DMD ladder at the TARGET resolution - the model synthesizes real
|
| 238 |
-
detail (RTX-class upscalers only sharpen what exists). Runs in 65-frame
|
| 239 |
-
windows with cross-fade (a 24GB card survives 1920x1088 refines); memory
|
| 240 |
-
bank and per-shot previews stay base-res; failures fall back to the base
|
| 241 |
-
frames. Audio is untouched.
|
| 242 |
-
|
| 243 |
-
### 17. Reference scheduling upgrades (`JoyEcho_RefPicker` + `_Generate`)
|
| 244 |
-
- Script-carried ref pinning: `{"prompts": [...], "refs": {"zara":
|
| 245 |
-
"zara_file.png"}}` pins a scene-matched reference per character (a
|
| 246 |
-
full-scene ref SETS the render's scene - match it to the script).
|
| 247 |
-
- Re-entry injection: a character returning after a 3+-shot absence gets
|
| 248 |
-
their ref re-injected at the return shot automatically (the rolling memory
|
| 249 |
-
window is 4; long absences otherwise re-invent the character).
|
| 250 |
-
- Generate's ref dedup is schedule-aware (the same image scheduled at two
|
| 251 |
-
shots survives; cap 6 scheduled entries).
|
| 252 |
-
|
| 253 |
-
### 18. Robustness
|
| 254 |
-
- Pipelines no longer derive their working dtype from
|
| 255 |
-
`next(parameters()).dtype` (an fp8 first-param crashed `torch.randn`);
|
| 256 |
-
fp8 dtypes are skipped with a bfloat16 fallback.
|
| 257 |
-
- fp8 gemma swap accepts both `.scale_weight` and `.weight_scale` layouts
|
| 258 |
-
and warns loudly on zero matches instead of silently staying bf16.
|
| 259 |
-
|
| 260 |
-
### 19. Finishing:
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
license_name: ltx-2-community-license
|
| 4 |
+
license_link: https://huggingface.co/Lightricks/LTX-2/blob/main/LICENSE.txt
|
| 5 |
+
tags:
|
| 6 |
+
- comfyui
|
| 7 |
+
- joyai-echo
|
| 8 |
+
- ltx-video
|
| 9 |
+
- multishot
|
| 10 |
+
- patch
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# JoyAI-Echo GGUF nodes — multishot fixes + automation patch
|
| 14 |
+
|
| 15 |
+
A set of bug fixes and features layered on top of the community
|
| 16 |
+
`ComfyUI_JoyAI_Echo_GGUF_Nodes` pack (the Rebels GGUF loader stack around
|
| 17 |
+
JoyAI-Echo). Everything here targets the **multi-shot** path (`JoyEcho_Generate`
|
| 18 |
+
+ the discrete Rebels loaders / `JoyEcho_ModelLoader`).
|
| 19 |
+
|
| 20 |
+
This is a **patch drop**, not a standalone pack: copy these files over a working
|
| 21 |
+
install of the same pack (back up first). The files are interdependent — in
|
| 22 |
+
particular `nodes.py` calls new signatures added to the two `libs/` files, so
|
| 23 |
+
apply them together.
|
| 24 |
+
|
| 25 |
+
Tested on an RTX 5090 (32 GB) and a 3090 (24 GB), ComfyUI 0.26–0.27,
|
| 26 |
+
torch 2.8–2.11, with the JoyAI-Echo bf16 release and self-built Q8 GGUFs.
|
| 27 |
+
|
| 28 |
+
---
|
| 29 |
+
|
| 30 |
+
## Files in this package
|
| 31 |
+
|
| 32 |
+
```
|
| 33 |
+
nodes.py # JoyEcho_TextEncode / _Generate / _ModelLoader / _LLMEnhance
|
| 34 |
+
__init__.py # registrations for the new nodes
|
| 35 |
+
rebels_loaders.py # discrete GGUF loaders (text-encoder fixes)
|
| 36 |
+
joyecho_prompt_source.py (new node) # one dropdown: .txt briefs + .json scripts
|
| 37 |
+
joyecho_ref_picker.py (new node) # auto reference-image picker by character name
|
| 38 |
+
joyecho_ref_batch.py (new node) # None-tolerant image batcher
|
| 39 |
+
joyecho_script_picker.py (new node) # JSON dropdown (superseded by PromptSource)
|
| 40 |
+
libs/ltx_distillation/models/ltx_wrapper.py # fp8 quantization passthrough
|
| 41 |
+
libs/ltx_core/loader/fuse_loras.py # kohya-LoRA fusion + alpha scaling + fuse telemetry
|
| 42 |
+
libs/ltx_core/quantization/policy.py # fp8_scaled_mm_torch policy (+ sm_89 gate)
|
| 43 |
+
libs/ltx_core/quantization/fp8_torch_mm.py # native-fp8 Linear forward (torch._scaled_mm)
|
| 44 |
+
libs/ltx_distillation/utils.py # tiled VAE decode
|
| 45 |
+
libs/ltx_distillation/inference/memory_multishot.py # memory bank TRIM FIX (critical)
|
| 46 |
+
libs/ltx_distillation/inference/bidirectional_pipeline.py # dtype hardening vs fp8 params
|
| 47 |
+
libs/ltx_distillation/inference/memory_bidirectional_pipeline.py # dtype hardening vs fp8 params
|
| 48 |
+
prompts/long_story_writer_system_prompt.md # (optional) de-musicked + character-age edits
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
The files are interdependent - apply the whole set together, never cherry-pick
|
| 52 |
+
(a nodes.py newer than its libs/ raises AttributeError at load).
|
| 53 |
+
|
| 54 |
+
---
|
| 55 |
+
|
| 56 |
+
## Bug fixes
|
| 57 |
+
|
| 58 |
+
### 1. `enable_audio_memory=False` silently disabled ALL cross-shot memory
|
| 59 |
+
The pack computed `audio_memory_latent=None` when audio memory was off, and the
|
| 60 |
+
video **memory-bank save was gated on that latent being non-None** — so with
|
| 61 |
+
audio memory off (the standard anti-drone setting) the bank never filled and
|
| 62 |
+
cross-shot **identity** silently died (symptom: `memory_size=0` every shot even
|
| 63 |
+
with `memory_max_size=7`; a new face each shot).
|
| 64 |
+
Fix: memory storage is now unconditional; `enable_audio_memory` gates only the
|
| 65 |
+
audio-memory **injection** path. Verify: console `memory_size=` should climb
|
| 66 |
+
0,1,2,… capped at your `memory_max_size`. (`nodes.py`)
|
| 67 |
+
|
| 68 |
+
### 1b. Memory bank trim was a NO-OP whenever `memory_max_size <= num_fix_frames` (CRITICAL)
|
| 69 |
+
`PairedAudioVideoMemoryBank._trim()` computed `tail[-keep_tail:]` - and when
|
| 70 |
+
`keep_tail == 0` (e.g. the common max_size=3 / num_fix_frames=3 combo),
|
| 71 |
+
`tail[-0:]` is the WHOLE list, so the bank grew unbounded: every shot
|
| 72 |
+
conditioned on EVERY prior shot. Symptom: console `memory_size=` climbing
|
| 73 |
+
0,1,2,...,N-1 past your cap, and severe compounding quality degradation over
|
| 74 |
+
long runs (waxy skin, contrast crush, smearing by the late shots - the "gets
|
| 75 |
+
worse as it goes" failure). Fixed with a proper zero-tail branch + anchor
|
| 76 |
+
clamp; `memory_size=` now freezes at your cap. This one fix eliminated the entire
|
| 77 |
+
long-run degradation in our tests. (`libs/.../memory_multishot.py`)
|
| 78 |
+
|
| 79 |
+
### 2. GGUF text-encoder loader (`RebelsJE_TextEncoder`)
|
| 80 |
+
Two fixes so a text-only Gemma-3 GGUF loads cleanly:
|
| 81 |
+
- **meta-strip**: drop `vision_tower` / `multi_modal_projector` / `lm_head`
|
| 82 |
+
(the text-only GGUF has no weights for them → "Cannot copy out of meta tensor").
|
| 83 |
+
- **device-unify**: pin the embeddings-processor to the encoder's actual device
|
| 84 |
+
(GGUF Gemma runs on CPU while the connector was on cuda → addmm device mismatch).
|
| 85 |
+
- **fp8 gemma scale-key layouts**: the `our_fp8` swap only recognized its own
|
| 86 |
+
export layout (bare module names + `.scale_weight`); standard HF/comfy-style
|
| 87 |
+
fp8 gemma files (`<module>.weight` + `.weight_scale`, e.g. community
|
| 88 |
+
abliterated builds) silently loaded with **zero modules swapped** — the
|
| 89 |
+
encoder stayed bf16 with no indication. Both layouts are now accepted
|
| 90 |
+
(per-tensor scalar scales; per-channel scales are skipped and those modules
|
| 91 |
+
stay bf16), and a loud warning prints if a file matches neither.
|
| 92 |
+
(`rebels_loaders.py`)
|
| 93 |
+
|
| 94 |
+
---
|
| 95 |
+
|
| 96 |
+
## Features
|
| 97 |
+
|
| 98 |
+
### 3. Split per-domain negative lever (`JoyEcho_TextEncode`)
|
| 99 |
+
The DMD pipeline has no CFG, so the only steering lever is embedding-space.
|
| 100 |
+
Instead of one `negative_prompt`/`negative_scale` that steers both branches,
|
| 101 |
+
this splits it:
|
| 102 |
+
- `negative_prompt_video` / `negative_scale_video` — kills burned-in
|
| 103 |
+
captions/subtitles. Working value ~0.5. **Above ~0.8 it over-rotates the
|
| 104 |
+
video context and locks every shot to shot 1's composition** (scene-lock).
|
| 105 |
+
- `negative_prompt_audio` / `negative_scale_audio` — kills invented
|
| 106 |
+
music/score. Keep ≤ ~0.4 or dialogue suffers.
|
| 107 |
+
Steering is norm-preserving (RescaleCFG-style): `cond' = renorm(cond + s*(cond − neg))`.
|
| 108 |
+
Old single-widget names still work as a fallback. (`nodes.py`)
|
| 109 |
+
|
| 110 |
+
### 4. Passthrough mode (`JoyEcho_LLMEnhance`)
|
| 111 |
+
`mode = "passthrough (raw JSON, skip LLM)"` — feed a finished
|
| 112 |
+
`{"prompts":[...]}` script straight through with no LLM call / no API key.
|
| 113 |
+
Auto-detects when `story_idea` already parses as that JSON. (`nodes.py`)
|
| 114 |
+
|
| 115 |
+
### 5. Reference-image conditioning — I2V-as-reference (`JoyEcho_Generate`)
|
| 116 |
+
New `reference_image` (IMAGE batch, up to 4). Identity references are prepended
|
| 117 |
+
as **video-only conditioning clips** at the memory-encode step — they are
|
| 118 |
+
**never** written into the paired audio/video bank. (An earlier attempt that
|
| 119 |
+
seeded refs into the bank with zero-filled audio latents injected loud
|
| 120 |
+
background noise with 2+ refs; video-only conditioning avoids it entirely.)
|
| 121 |
+
Also new: `head_trim_frames` (auto 8 with refs) drops the first N frames of each
|
| 122 |
+
shot, where the model morphs out of the reference/memory content. The trim is
|
| 123 |
+
applied once right after decode, so the final output, the per-shot preview
|
| 124 |
+
files, and any external concat of them stay frame-identical. (`nodes.py`)
|
| 125 |
+
|
| 126 |
+
### 6. Shot transitions (`JoyEcho_Generate`)
|
| 127 |
+
`transition`: `cut` (original) / `dissolve` (overlap cross-dissolve + equal-power
|
| 128 |
+
audio crossfade) / `vhs_glitch` (analog static burst at each boundary: snow,
|
| 129 |
+
tear bands, dropout lines + a raised-cosine tape-noise audio bed).
|
| 130 |
+
`transition_frames`, `glitch_intensity` tune it. (`nodes.py`)
|
| 131 |
+
|
| 132 |
+
### 7. fp8 transformer quantization (`JoyEcho_ModelLoader`)
|
| 133 |
+
New `fp8_transformer` toggle. Quantizes the DiT's attention/FF linear weights to
|
| 134 |
+
`float8_e4m3fn` **at load, from the normal bf16 checkpoint** (uses the vendored
|
| 135 |
+
`ltx_core.quantization.QuantizationPolicy.fp8_cast()` — upcasts per-layer at
|
| 136 |
+
inference). Roughly halves DiT weight memory and halves sequential-offload PCIe
|
| 137 |
+
traffic; keeps memory training + all tensors; VAEs/text-encoder/non-linears stay
|
| 138 |
+
bf16. Ignored when a GGUF DiT is selected (already quantized).
|
| 139 |
+
(`nodes.py` + `libs/ltx_distillation/models/ltx_wrapper.py` — new `quantization`
|
| 140 |
+
param; the quantized build path skips the post-load dtype cast that would
|
| 141 |
+
otherwise silently upcast fp8 back to bf16.)
|
| 142 |
+
|
| 143 |
+
### 8. Tiled VAE decode (`JoyEcho_Generate`)
|
| 144 |
+
Decoding a long high-res shot (e.g. 241f @ 1280×736) in one pass hard-aborts the
|
| 145 |
+
VAE decode on a 24–32 GB card (fatal cuDNN abort mid-conv, not a catchable OOM).
|
| 146 |
+
New `decode_tiling` (`auto`/`on`/`off`) routes decode through the vendored
|
| 147 |
+
`VideoDecoder.tiled_decode` — **temporal-only** 64-frame chunks with 24-frame
|
| 148 |
+
blended overlap (no spatial tiles → no spatial seams), streaming each chunk to
|
| 149 |
+
CPU. `auto` engages only above a size threshold, so small renders keep the
|
| 150 |
+
original single-pass decode bit-for-bit.
|
| 151 |
+
(`nodes.py` + `libs/ltx_distillation/utils.py` — `decode_benchmark_sample` gains
|
| 152 |
+
a `video_tiling_config` kwarg + `_decode_video_tiled_uint8`.)
|
| 153 |
+
|
| 154 |
+
### 9. Model dropdown (`JoyEcho_ModelLoader`)
|
| 155 |
+
New `model_file` combo lists every `.safetensors` / `.gguf` under the ComfyUI
|
| 156 |
+
`checkpoints` / `diffusion_models` / `unet` dirs. Pick a `.safetensors` → full
|
| 157 |
+
checkpoint (replaces `checkpoint_path`); pick a `.gguf` → DiT loaded from GGUF
|
| 158 |
+
while `checkpoint_path` still supplies the VAEs / vocoder / text connectors.
|
| 159 |
+
`"(use checkpoint_path)"` keeps the old typed-path behavior. A matching
|
| 160 |
+
`lora_file` dropdown lists every `.safetensors` under `models/loras`
|
| 161 |
+
(applied at `lora_strength` on the safetensors DiT path; ignored for GGUF). Plus a clear
|
| 162 |
+
early error if `gemma_path` is a `.gguf`/file/sidecar-less dir (this loader
|
| 163 |
+
needs the HF `gemma-3-12b-it` folder; GGUF Gemma only works via
|
| 164 |
+
`RebelsJE_TextEncoder`). (`nodes.py`)
|
| 165 |
+
|
| 166 |
+
### 10. LoRA loading hardening (`JoyEcho_ModelLoader` + `libs/.../fuse_loras.py`)
|
| 167 |
+
- A `lora_file` dropdown picks LoRAs from `models/loras` (existing
|
| 168 |
+
`lora_strength` widget applies).
|
| 169 |
+
- Fusion now supports **kohya naming** (`lora_down`/`lora_up`) in addition to
|
| 170 |
+
PEFT (`lora_A`/`lora_B`), with standard `alpha/rank` scaling — previously a
|
| 171 |
+
kohya-named LoRA silently did NOTHING (zero keys matched, no warning).
|
| 172 |
+
- Fusion prints how many weights fused, and WARNS LOUDLY when a provided LoRA
|
| 173 |
+
matched zero keys.
|
| 174 |
+
- The loader refuses **ComfyUI-quantized checkpoints** (`.comfy_quant` marker
|
| 175 |
+
tensors, e.g. "fp8mixed learned" builds) with a clear error: this loader
|
| 176 |
+
never applies their weight scales (the model would silently load mis-scaled)
|
| 177 |
+
and LoRA fusion on them crashes with shape errors. Use bf16 checkpoints.
|
| 178 |
+
|
| 179 |
+
### 11. Automation / batching nodes (new)
|
| 180 |
+
- **`JoyEcho_PromptSource`** — one dropdown listing LPFF-style `.txt` briefs
|
| 181 |
+
(from the inspire-pack prompts tree) **and** passthrough `.json` scripts
|
| 182 |
+
(`input/joyecho_prompts/`). Multi-block briefs fan out like
|
| 183 |
+
LoadPromptsFromFile. Emits `story_idea` (→ LLMEnhance) + `character`
|
| 184 |
+
(→ RefPicker) + `count`. Replaces the LPFF→UnzipPrompt chain and lets you
|
| 185 |
+
switch prompt sources with one dropdown instead of rewiring.
|
| 186 |
+
- **`JoyEcho_RefPicker`** — auto-selects a character reference image from a
|
| 187 |
+
folder tree keyed by character name (a `character_pick` dropdown of the
|
| 188 |
+
folder names, a typed/wired `character` string, or a prompt scan — dialogue
|
| 189 |
+
mentions are stripped so only the on-screen subject wins). The dropdown
|
| 190 |
+
survives model refreshes, an explicitly named character that matches no
|
| 191 |
+
folder refuses to fall back to the prompt scan (a wiped/typo'd name can't
|
| 192 |
+
silently become the wrong character's face), and the cache signature
|
| 193 |
+
includes the prompt text (without it, ComfyUI could serve a cached pick
|
| 194 |
+
from a previous queue item). `on_no_match=no_reference` returns nothing so
|
| 195 |
+
a batch keeps running.
|
| 196 |
+
- **`JoyEcho_RefBatch`** — None-tolerant image batcher: combines up to 4
|
| 197 |
+
optional IMAGE inputs (e.g. two RefPickers for a two-character shot), skips
|
| 198 |
+
missing refs, resizes mismatched sizes to the first image, outputs `None` if
|
| 199 |
+
all are missing (Generate then just skips identity seeding). The stock KJNodes
|
| 200 |
+
`ImageBatchMulti` crashes with `'NoneType' has no attribute 'shape'` on a
|
| 201 |
+
missing ref; this replaces it.
|
| 202 |
+
- **`JoyEcho_ScriptPicker`** — JSON dropdown (superseded by PromptSource; kept
|
| 203 |
+
for compatibility).
|
| 204 |
+
|
| 205 |
+
### 12. GPU encode hot-swap (`JoyEcho_TextEncode`)
|
| 206 |
+
With `low_vram` the Gemma encoder used to encode every shot on CPU (~10s+ per
|
| 207 |
+
shot). The encode pass now borrows the (idle) GPU when the encoder fits free
|
| 208 |
+
VRAM - with a fits-check, an OOM fallback to CPU, and a move-back before the
|
| 209 |
+
denoise phase. 20-shot encodes drop from minutes to seconds. (`nodes.py`)
|
| 210 |
+
|
| 211 |
+
### 13. `encoder_fp8` (`JoyEcho_ModelLoader`)
|
| 212 |
+
Stores the Gemma encoder's linear weights as float8_e4m3fn with per-layer
|
| 213 |
+
upcast at encode (encode runs once per item, so the upcast tax that makes
|
| 214 |
+
fp8 slow on the DiT is irrelevant here). Wrapper drops ~24GB -> ~21GB and the
|
| 215 |
+
GPU hot-swap engages on 32GB cards; JD's connector projections stay bf16.
|
| 216 |
+
|
| 217 |
+
### 14. `fp8_scaled_mm` (`JoyEcho_ModelLoader`) - native fp8 compute
|
| 218 |
+
Stores the DiT's attention/FF linears as fp8 AND runs the matmuls natively
|
| 219 |
+
via `torch._scaled_mm` - no per-layer upcast tax (measured x2.8 raw kernel /
|
| 220 |
+
x1.5 end-to-end vs bf16 on an RTX 5090). ~22GB resident enables
|
| 221 |
+
`sequential_offload=False` at moderate resolutions. REQUIREMENTS: sm_89+
|
| 222 |
+
GPU (RTX 40/50 - clear error on older cards, with a per-device runtime
|
| 223 |
+
fallback to upcast), and a **bf16 source checkpoint** (an fp8 FILE would load
|
| 224 |
+
every tensor fp8 with the cast skipped and crash the noise path - guarded
|
| 225 |
+
with a clear error). Tensorwise dynamic activation quant: A/B your content
|
| 226 |
+
before adopting.
|
| 227 |
+
|
| 228 |
+
### 15. `resident_blocks` (`JoyEcho_Generate`)
|
| 229 |
+
Sequential offload middle ground: pin the first N of 48 transformer blocks
|
| 230 |
+
permanently on GPU, stream the rest. N=24 halves the per-step PCIe traffic;
|
| 231 |
+
raise until VRAM is nearly full. Composes with fp8 modes (fp8 blocks are
|
| 232 |
+
half the bytes both resident and streamed).
|
| 233 |
+
|
| 234 |
+
### 16. Hires-fix second pass (`JoyEcho_Generate`)
|
| 235 |
+
`hires_factor` (>1.0) + `hires_denoise`: after all shots render, each shot is
|
| 236 |
+
bicubic-upscaled, VAE re-encoded, re-noised at a tail sigma and re-denoised
|
| 237 |
+
through the DMD ladder at the TARGET resolution - the model synthesizes real
|
| 238 |
+
detail (RTX-class upscalers only sharpen what exists). Runs in 65-frame
|
| 239 |
+
windows with cross-fade (a 24GB card survives 1920x1088 refines); memory
|
| 240 |
+
bank and per-shot previews stay base-res; failures fall back to the base
|
| 241 |
+
frames. Audio is untouched.
|
| 242 |
+
|
| 243 |
+
### 17. Reference scheduling upgrades (`JoyEcho_RefPicker` + `_Generate`)
|
| 244 |
+
- Script-carried ref pinning: `{"prompts": [...], "refs": {"zara":
|
| 245 |
+
"zara_file.png"}}` pins a scene-matched reference per character (a
|
| 246 |
+
full-scene ref SETS the render's scene - match it to the script).
|
| 247 |
+
- Re-entry injection: a character returning after a 3+-shot absence gets
|
| 248 |
+
their ref re-injected at the return shot automatically (the rolling memory
|
| 249 |
+
window is 4; long absences otherwise re-invent the character).
|
| 250 |
+
- Generate's ref dedup is schedule-aware (the same image scheduled at two
|
| 251 |
+
shots survives; cap 6 scheduled entries).
|
| 252 |
+
|
| 253 |
+
### 18. Robustness
|
| 254 |
+
- Pipelines no longer derive their working dtype from
|
| 255 |
+
`next(parameters()).dtype` (an fp8 first-param crashed `torch.randn`);
|
| 256 |
+
fp8 dtypes are skipped with a bfloat16 fallback.
|
| 257 |
+
- fp8 gemma swap accepts both `.scale_weight` and `.weight_scale` layouts
|
| 258 |
+
and warns loudly on zero matches instead of silently staying bf16.
|
| 259 |
+
|
| 260 |
+
### 19. Finishing: who builds your master (READ THIS before touching hires)
|
| 261 |
+
`hires_factor` is a ROUTING switch, not a quality slider - it decides which
|
| 262 |
+
pipeline builds your final video:
|
| 263 |
+
|
| 264 |
+
| you want | hires_factor | hires_denoise | master comes from |
|
| 265 |
+
|---|---|---|---|
|
| 266 |
+
| **default: zero detail-shimmer** | **1.0** | (ignored) | base shots, upscaled by AutoFinish (bicubic + contrast-adaptive sharpen - deterministic, seconds per shot) |
|
| 267 |
+
| synthesized detail (pores/hair), accepts slight per-frame texture shimmer | 1.5 | subtle / medium / strong | your refined shots, used as-is (AutoFinish skips its own upscale) |
|
| 268 |
+
| deterministic upscale baked into the shot files | 1.5 | spatial | spatial-upscaled shots - EVEN latent grids only (height AND width /32 must be even: 768-height yes, 736 no) |
|
| 269 |
+
| the old RTX path | 1.0 | (ignored) | base shots via RTXBatchVideoUpscale (`upscale_mode: rtx (legacy)` on the AutoFinish node) |
|
| 270 |
+
|
| 271 |
+
- **Judge and publish only the `*_MASTER.mp4`.** The in-graph SaveVideo
|
| 272 |
+
output (prefixed `PREVIEW` in the shipped workflow) is a convenience
|
| 273 |
+
preview: its re-encode is bit-starved and shows artifacts the master does
|
| 274 |
+
not have. This is a ComfyUI limitation, not a render problem.
|
| 275 |
+
- Resolutions: everything works at any /32 size; only the `spatial` hires
|
| 276 |
+
mode additionally needs the /32 result EVEN on both axes (1280x768 and
|
| 277 |
+
1344x768 qualify; 1280x736 and 1536x864 do not - spatial will smear one
|
| 278 |
+
edge and warn in the console).
|
| 279 |
+
- All other widgets are genuinely free: seed, num_frames (long shots are
|
| 280 |
+
fine - the old ~10s lip-sync limit was the fps bug, now fixed), fps,
|
| 281 |
+
memory sizes, head_trim.
|
| 282 |
+
- The master pipeline re-encodes with `bf 0` + `tune grain` end to end, so
|
| 283 |
+
masters never reintroduce B-frame pumping.
|
| 284 |
+
|
| 285 |
+
---
|
| 286 |
+
|
| 287 |
+
## Applying
|
| 288 |
+
|
| 289 |
+
1. Back up your existing pack folder.
|
| 290 |
+
2. Copy each file over the same relative path in
|
| 291 |
+
`ComfyUI/custom_nodes/ComfyUI_JoyAI_Echo_GGUF_Nodes/`.
|
| 292 |
+
3. Restart ComfyUI. New widgets append at the **end** of existing nodes, so
|
| 293 |
+
saved graphs keep their values; the four new nodes appear under the
|
| 294 |
+
`JoyAI-Echo` category. Press `R` after adding model files to refresh the
|
| 295 |
+
`model_file` dropdown.
|
| 296 |
+
|
| 297 |
+
The `libs/` files must match the vendored `ltx_core` / `ltx_distillation` in
|
| 298 |
+
your pack (same JoyAI-Echo release). If your `libs/` differ substantially,
|
| 299 |
+
cherry-pick the changes described above rather than overwriting.
|
| 300 |
+
|
| 301 |
+
Not included (intentionally): model weights, the `gemma_assets/` tokenizer
|
| 302 |
+
binaries, `.bak` snapshots, and `__pycache__`.
|
| 303 |
+
|
| 304 |
+
---
|
| 305 |
+
|
| 306 |
+
## Credits
|
| 307 |
+
|
| 308 |
+
This patch stands on other people's work:
|
| 309 |
+
|
| 310 |
+
- **JD Joy Future Academy** - [JoyAI-Echo](https://huggingface.co/jdopensource/JoyAI-Echo), the multishot memory model this whole stack serves (research / non-commercial license).
|
| 311 |
+
- **Lightricks** - [LTX-2 / LTX-2.3](https://huggingface.co/Lightricks/LTX-2.3) (LTX-2 Community License).
|
| 312 |
+
- **TenStrip** - the [LTX2.3 DMD LoRAs](https://huggingface.co/TenStrip/LTX2.3_DMD_Lora); the hires `strong (tenstrip 4-step)` mode uses his published upscale sigma ladder verbatim.
|
| 313 |
+
- **RealRebelAI** - the Rebels GGUF loader stack this patches, and the [Q6_K_RM GGUF](https://huggingface.co/realrebelai/JoyAI-Echo_GGUF) whose tensor canon the self-built GGUFs mirror.
|
| 314 |
+
- **Comfy-Org** - the comfy-quants `int8_tensorwise` + ConvRot export recipe behind the INT8 checkpoint.
|
| 315 |
+
- **Google** - Gemma 3 12B, the text encoder (Gemma license).
|
nodes.py
CHANGED
|
@@ -1199,13 +1199,17 @@ class JoyEcho_Generate:
|
|
| 1199 |
}),
|
| 1200 |
"hires_factor": ("FLOAT", {
|
| 1201 |
"default": 1.0, "min": 1.0, "max": 2.0, "step": 0.05,
|
| 1202 |
-
"tooltip": "
|
| 1203 |
-
"
|
| 1204 |
-
"
|
| 1205 |
-
"
|
| 1206 |
-
"
|
| 1207 |
-
"
|
| 1208 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1209 |
}),
|
| 1210 |
"hires_denoise": (["subtle (1 step)", "medium (2 steps)",
|
| 1211 |
"strong (tenstrip 4-step)",
|
|
|
|
| 1199 |
}),
|
| 1200 |
"hires_factor": ("FLOAT", {
|
| 1201 |
"default": 1.0, "min": 1.0, "max": 2.0, "step": 0.05,
|
| 1202 |
+
"tooltip": "ROUTING switch, not a quality slider - it decides who builds "
|
| 1203 |
+
"your master. 1.0 (RECOMMENDED): shots stay base-res and the "
|
| 1204 |
+
"AutoFinish worker upscales them deterministically "
|
| 1205 |
+
"(bicubic+CAS) - zero per-frame detail shimmer. Above 1.0: the "
|
| 1206 |
+
"selected hires_denoise pass runs in-render and the master is "
|
| 1207 |
+
"built from ITS output instead (AutoFinish detects the hires "
|
| 1208 |
+
"shots and skips its own upscale). Only raise this when you "
|
| 1209 |
+
"deliberately want the refine modes' synthesized detail "
|
| 1210 |
+
"(slight texture shimmer) or the spatial mode (even /32 dims "
|
| 1211 |
+
"only, e.g. 768-height). Judge results from the *_MASTER.mp4 "
|
| 1212 |
+
"file, never the in-canvas preview.",
|
| 1213 |
}),
|
| 1214 |
"hires_denoise": (["subtle (1 step)", "medium (2 steps)",
|
| 1215 |
"strong (tenstrip 4-step)",
|
workflow/JoyEcho_Multishot_Workflow_PUBLIC.json
CHANGED
|
@@ -193,232 +193,11 @@
|
|
| 193 |
}
|
| 194 |
},
|
| 195 |
"widgets_values": [
|
| 196 |
-
"joyecho/
|
| 197 |
"auto",
|
| 198 |
"auto"
|
| 199 |
]
|
| 200 |
},
|
| 201 |
-
{
|
| 202 |
-
"id": 6,
|
| 203 |
-
"type": "CreateVideo",
|
| 204 |
-
"pos": [
|
| 205 |
-
4328.590366291457,
|
| 206 |
-
359.91012828201144
|
| 207 |
-
],
|
| 208 |
-
"size": [
|
| 209 |
-
301.3775449810605,
|
| 210 |
-
102
|
| 211 |
-
],
|
| 212 |
-
"flags": {},
|
| 213 |
-
"order": 14,
|
| 214 |
-
"mode": 0,
|
| 215 |
-
"inputs": [
|
| 216 |
-
{
|
| 217 |
-
"localized_name": "images",
|
| 218 |
-
"name": "images",
|
| 219 |
-
"type": "IMAGE",
|
| 220 |
-
"link": 113
|
| 221 |
-
},
|
| 222 |
-
{
|
| 223 |
-
"localized_name": "audio",
|
| 224 |
-
"name": "audio",
|
| 225 |
-
"shape": 7,
|
| 226 |
-
"type": "AUDIO",
|
| 227 |
-
"link": 108
|
| 228 |
-
},
|
| 229 |
-
{
|
| 230 |
-
"localized_name": "fps",
|
| 231 |
-
"name": "fps",
|
| 232 |
-
"type": "FLOAT",
|
| 233 |
-
"widget": {
|
| 234 |
-
"name": "fps"
|
| 235 |
-
},
|
| 236 |
-
"link": null
|
| 237 |
-
},
|
| 238 |
-
{
|
| 239 |
-
"localized_name": "bit_depth",
|
| 240 |
-
"name": "bit_depth",
|
| 241 |
-
"shape": 7,
|
| 242 |
-
"type": "INT",
|
| 243 |
-
"widget": {
|
| 244 |
-
"name": "bit_depth"
|
| 245 |
-
},
|
| 246 |
-
"link": null
|
| 247 |
-
}
|
| 248 |
-
],
|
| 249 |
-
"outputs": [
|
| 250 |
-
{
|
| 251 |
-
"localized_name": "VIDEO",
|
| 252 |
-
"name": "VIDEO",
|
| 253 |
-
"type": "VIDEO",
|
| 254 |
-
"slot_index": 0,
|
| 255 |
-
"links": [
|
| 256 |
-
10
|
| 257 |
-
]
|
| 258 |
-
}
|
| 259 |
-
],
|
| 260 |
-
"title": "Create Video (Merge All Shots)",
|
| 261 |
-
"properties": {
|
| 262 |
-
"cnr_id": "comfy-core",
|
| 263 |
-
"ver": "0.26.2",
|
| 264 |
-
"Node name for S&R": "CreateVideo",
|
| 265 |
-
"ue_properties": {
|
| 266 |
-
"widget_ue_connectable": {},
|
| 267 |
-
"version": "7.8",
|
| 268 |
-
"input_ue_unconnectable": {}
|
| 269 |
-
}
|
| 270 |
-
},
|
| 271 |
-
"widgets_values": [
|
| 272 |
-
25,
|
| 273 |
-
8
|
| 274 |
-
]
|
| 275 |
-
},
|
| 276 |
-
{
|
| 277 |
-
"id": 59,
|
| 278 |
-
"type": "JoyEcho_LLMEnhance",
|
| 279 |
-
"pos": [
|
| 280 |
-
900,
|
| 281 |
-
100
|
| 282 |
-
],
|
| 283 |
-
"size": [
|
| 284 |
-
1161.0279043079718,
|
| 285 |
-
736.9512031915835
|
| 286 |
-
],
|
| 287 |
-
"flags": {},
|
| 288 |
-
"order": 8,
|
| 289 |
-
"mode": 0,
|
| 290 |
-
"inputs": [
|
| 291 |
-
{
|
| 292 |
-
"localized_name": "story_idea",
|
| 293 |
-
"name": "story_idea",
|
| 294 |
-
"type": "STRING",
|
| 295 |
-
"widget": {
|
| 296 |
-
"name": "story_idea"
|
| 297 |
-
},
|
| 298 |
-
"link": 114
|
| 299 |
-
},
|
| 300 |
-
{
|
| 301 |
-
"localized_name": "mode",
|
| 302 |
-
"name": "mode",
|
| 303 |
-
"type": "COMBO",
|
| 304 |
-
"widget": {
|
| 305 |
-
"name": "mode"
|
| 306 |
-
},
|
| 307 |
-
"link": null
|
| 308 |
-
},
|
| 309 |
-
{
|
| 310 |
-
"localized_name": "api_key",
|
| 311 |
-
"name": "api_key",
|
| 312 |
-
"type": "STRING",
|
| 313 |
-
"widget": {
|
| 314 |
-
"name": "api_key"
|
| 315 |
-
},
|
| 316 |
-
"link": null
|
| 317 |
-
},
|
| 318 |
-
{
|
| 319 |
-
"localized_name": "system_prompt",
|
| 320 |
-
"name": "system_prompt",
|
| 321 |
-
"type": "STRING",
|
| 322 |
-
"widget": {
|
| 323 |
-
"name": "system_prompt"
|
| 324 |
-
},
|
| 325 |
-
"link": null
|
| 326 |
-
},
|
| 327 |
-
{
|
| 328 |
-
"localized_name": "base_url",
|
| 329 |
-
"name": "base_url",
|
| 330 |
-
"shape": 7,
|
| 331 |
-
"type": "STRING",
|
| 332 |
-
"widget": {
|
| 333 |
-
"name": "base_url"
|
| 334 |
-
},
|
| 335 |
-
"link": null
|
| 336 |
-
},
|
| 337 |
-
{
|
| 338 |
-
"localized_name": "model_name",
|
| 339 |
-
"name": "model_name",
|
| 340 |
-
"shape": 7,
|
| 341 |
-
"type": "STRING",
|
| 342 |
-
"widget": {
|
| 343 |
-
"name": "model_name"
|
| 344 |
-
},
|
| 345 |
-
"link": null
|
| 346 |
-
},
|
| 347 |
-
{
|
| 348 |
-
"localized_name": "num_shots",
|
| 349 |
-
"name": "num_shots",
|
| 350 |
-
"shape": 7,
|
| 351 |
-
"type": "INT",
|
| 352 |
-
"widget": {
|
| 353 |
-
"name": "num_shots"
|
| 354 |
-
},
|
| 355 |
-
"link": null
|
| 356 |
-
},
|
| 357 |
-
{
|
| 358 |
-
"localized_name": "temperature",
|
| 359 |
-
"name": "temperature",
|
| 360 |
-
"shape": 7,
|
| 361 |
-
"type": "FLOAT",
|
| 362 |
-
"widget": {
|
| 363 |
-
"name": "temperature"
|
| 364 |
-
},
|
| 365 |
-
"link": null
|
| 366 |
-
},
|
| 367 |
-
{
|
| 368 |
-
"localized_name": "num_frames",
|
| 369 |
-
"name": "num_frames",
|
| 370 |
-
"shape": 7,
|
| 371 |
-
"type": "INT",
|
| 372 |
-
"widget": {
|
| 373 |
-
"name": "num_frames"
|
| 374 |
-
},
|
| 375 |
-
"link": null
|
| 376 |
-
},
|
| 377 |
-
{
|
| 378 |
-
"localized_name": "fps",
|
| 379 |
-
"name": "fps",
|
| 380 |
-
"shape": 7,
|
| 381 |
-
"type": "FLOAT",
|
| 382 |
-
"widget": {
|
| 383 |
-
"name": "fps"
|
| 384 |
-
},
|
| 385 |
-
"link": null
|
| 386 |
-
}
|
| 387 |
-
],
|
| 388 |
-
"outputs": [
|
| 389 |
-
{
|
| 390 |
-
"localized_name": "prompts_json",
|
| 391 |
-
"name": "prompts_json",
|
| 392 |
-
"type": "STRING",
|
| 393 |
-
"links": [
|
| 394 |
-
115,
|
| 395 |
-
116
|
| 396 |
-
]
|
| 397 |
-
}
|
| 398 |
-
],
|
| 399 |
-
"properties": {
|
| 400 |
-
"aux_id": "RealRebelAI/ComfyUI_JoyAI_Echo_GGUF_Nodes",
|
| 401 |
-
"ver": "0d9e32fcd2d255a16604368fcaa1875c380c7f3b",
|
| 402 |
-
"Node name for S&R": "JoyEcho_LLMEnhance",
|
| 403 |
-
"ue_properties": {
|
| 404 |
-
"widget_ue_connectable": {},
|
| 405 |
-
"input_ue_unconnectable": {},
|
| 406 |
-
"version": "7.8"
|
| 407 |
-
}
|
| 408 |
-
},
|
| 409 |
-
"widgets_values": [
|
| 410 |
-
"",
|
| 411 |
-
"long_story (multi-shot)",
|
| 412 |
-
"",
|
| 413 |
-
"",
|
| 414 |
-
"http://localhost:11434/v1",
|
| 415 |
-
"glm-5.2:cloud",
|
| 416 |
-
6,
|
| 417 |
-
0.7,
|
| 418 |
-
321,
|
| 419 |
-
25
|
| 420 |
-
]
|
| 421 |
-
},
|
| 422 |
{
|
| 423 |
"id": 65,
|
| 424 |
"type": "JoyEcho_LoraStacker",
|
|
@@ -723,7 +502,7 @@
|
|
| 723 |
},
|
| 724 |
"widgets_values": [
|
| 725 |
"by_seed",
|
| 726 |
-
|
| 727 |
"randomize",
|
| 728 |
"joyecho_refs",
|
| 729 |
"no_reference",
|
|
@@ -802,7 +581,7 @@
|
|
| 802 |
}
|
| 803 |
},
|
| 804 |
"widgets_values": [
|
| 805 |
-
"{\n \"prompts\": [\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a locked static medium close-up at her eye level on the small corner stage of an empty dive bar, hot magenta and blue stage lights raking across her from the rig above, a scuffed drum kit and a taped-up amp behind her, black walls layered with faded gig flyers, her head and shoulders filling most of the frame and her mouth fully visible. Quiet diegetic sound only: the low buzz of the stage lighting rig, a beer cooler humming off in the dark, and her voice close and dry on the camcorder mic. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_A is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_A's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. At a quick, natural speed, she stands still at the mic stand without touching it, looking into the lens, the lip movement aligning closely with the audio throughout the line. In a bright, quick voice with a playful edge, ID_A says, \\\"Alright, watch close. Five places, one me. Nothing carries this face around but one sentence, repeated like a chorus. That's the whole gig. Count the costume changes - there aren't any.\\\"\",\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a slow steady push-in to a medium close-up at her eye level in a late-night diner booth, teal and pink neon tubing burning in the window beside her and doubling in soft color across the chrome napkin holder and the red vinyl seat, her head and shoulders filling most of the frame and her mouth fully visible, a thick white coffee mug already on the table in front of her, untouched. Quiet diegetic sound only: the neon transformer buzzing in the window, a milkshake machine whirring somewhere behind the counter, and the vinyl seat creaking once as she settles. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_A is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_A's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. At a quick, natural speed, she sits still in the booth, looking into the lens, the lip movement aligning closely with the audio throughout the line. In a bright, quick voice with a playful edge, ID_A says, \\\"New room, new light, same everything else. Same jacket, same pins, same voice with the same attitude. If I drift even a little, you'd clock it instantly. So clock it.\\\"\",\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a locked static medium close-up at her eye level in a fluorescent-lit laundromat, a wall of mustard-yellow washing machines behind her with one drum tumbling mid-cycle, chipped mint-green floor tile, a rolling wire basket parked beside her, her head and shoulders filling most of the frame and her mouth fully visible. Quiet diegetic sound only: the tumbling dryer thumping in rhythm, coins rattling in a metal tray, and the fluorescent fixtures humming overhead. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_A is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_A's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. At a quick, natural speed, she leans one shoulder against a washer, standing still, looking into the lens, the lip movement aligning closely with the audio throughout the line. In a bright, quick voice with a playful edge, ID_A says, \\\"Third spot. Half a minute in. My voice hasn't moved an inch - same speed, same edge, same accent. The machines are louder than my identity crisis. Which is zero.\\\"\",\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a slow lateral drift to a medium close-up at her eye level in a cramped record store aisle, wooden crates of vinyl records packed tight on both sides, hand-written orange dividers poking up from the rows, a wall of album sleeves behind her in reds and yellows, warm tube amp light from the listening corner, her head and shoulders filling most of the frame and her mouth fully visible. Quiet diegetic sound only: a record crackling quietly on the shop turntable, sleeves flipping somewhere in another aisle, and the floorboards creaking under her weight shift. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_A is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_A's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. At a quick, natural speed, she stands still between the crates, hands in her jacket pockets, looking into the lens, the lip movement aligning closely with the audio throughout the line. In a bright, quick voice with a playful edge, ID_A says, \\\"Every one of these shots rendered separately. Different room, different seed, zero shared pixels. One sentence holds me together. Honestly? Most bands can't stay this consistent.\\\"\",\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a locked static medium close-up at her eye level on a flat gravel rooftop at dusk, the sky behind her banded deep orange to violet, strings of cafe bulbs slung between two vent stacks catching the edge of her jacket pins, the city below reduced to warm scattered windows, her head and shoulders filling most of the frame and her mouth fully visible. Quiet diegetic sound only: wind moving over the parapet, distant traffic far below, and one of the bulb strings ticking against its wire in the breeze. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_A is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_A's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. At a quick, natural speed, she stands still against the skyline, looking into the lens, the lip movement aligning closely with the audio throughout the line. In a bright, quick voice with a playful edge, ID_A says, \\\"So that's the trick - there isn't one. Same face, same voice, five rooms deep. If I'm a file, I'm at least a catchy one. See you around.\\\"\"\n ]\n}"
|
| 806 |
]
|
| 807 |
},
|
| 808 |
{
|
|
@@ -834,35 +613,6 @@
|
|
| 834 |
"color": "#432",
|
| 835 |
"bgcolor": "#653"
|
| 836 |
},
|
| 837 |
-
{
|
| 838 |
-
"id": 60,
|
| 839 |
-
"type": "Note",
|
| 840 |
-
"pos": [
|
| 841 |
-
2780.2351442980976,
|
| 842 |
-
806.7950609883953
|
| 843 |
-
],
|
| 844 |
-
"size": [
|
| 845 |
-
1057.751230034948,
|
| 846 |
-
248.99507986020944
|
| 847 |
-
],
|
| 848 |
-
"flags": {},
|
| 849 |
-
"order": 4,
|
| 850 |
-
"mode": 0,
|
| 851 |
-
"inputs": [],
|
| 852 |
-
"outputs": [],
|
| 853 |
-
"properties": {
|
| 854 |
-
"ue_properties": {
|
| 855 |
-
"widget_ue_connectable": {},
|
| 856 |
-
"version": "7.8",
|
| 857 |
-
"input_ue_unconnectable": {}
|
| 858 |
-
}
|
| 859 |
-
},
|
| 860 |
-
"widgets_values": [
|
| 861 |
-
"MODEL LOADER - what to set, what to leave\n------------------------------------------------\nSET THESE TWO:\n* model_file - the DiT checkpoint. fp8 build (23 GB) for 24 GB cards; bf16 (43 GB) for 32 GB+ (needs sequential offload).\n* gemma_file - your Gemma-3-12B text encoder, picked from models/text_encoders or models/clip. Single-file .safetensors or .gguf. A GGUF encoder is the light option (fits 24 GB systems easily).\n\nLEAVE ALONE UNLESS YOU KNOW WHY:\n* checkpoint_path - only needed when model_file is a .gguf (GGUF = DiT only; this must then point at a full safetensors to supply the VAEs + vocoder).\n* gemma_path - only for an HF gemma-3-12b-it DIRECTORY (dropdowns list files, not folders).\n* lora_file / lora_path - optional style LoRA. Ignored for GGUF DiTs.\n\nVRAM GUIDE:\n* 24 GB: fp8 model_file + low_vram ON (encoder runs on CPU; the encode is cached per prompt, so it only costs once).\n* 32 GB: bf16 model_file if downloaded; low_vram still recommended (the bf16 encoder alone is ~23 GB).\n* RTX 40/50-series: turn fp8_scaled_mm ON - native fp8 matmul, real speedup, and at moderate resolutions the DiT can run with sequential_offload OFF. Older GPUs: leave it off.\n* encoder_fp8 - halves encoder memory at a slight embedding shift (voice quality is the canary). Try it if RAM-starved."
|
| 862 |
-
],
|
| 863 |
-
"color": "#432",
|
| 864 |
-
"bgcolor": "#653"
|
| 865 |
-
},
|
| 866 |
{
|
| 867 |
"id": 11,
|
| 868 |
"type": "easy seed",
|
|
@@ -875,7 +625,7 @@
|
|
| 875 |
106
|
| 876 |
],
|
| 877 |
"flags": {},
|
| 878 |
-
"order":
|
| 879 |
"mode": 0,
|
| 880 |
"inputs": [
|
| 881 |
{
|
|
@@ -909,121 +659,115 @@
|
|
| 909 |
}
|
| 910 |
},
|
| 911 |
"widgets_values": [
|
| 912 |
-
|
| 913 |
-
"
|
| 914 |
null
|
| 915 |
]
|
| 916 |
},
|
| 917 |
{
|
| 918 |
-
"id":
|
| 919 |
-
"type": "
|
| 920 |
"pos": [
|
| 921 |
-
|
| 922 |
-
|
| 923 |
],
|
| 924 |
"size": [
|
| 925 |
-
|
| 926 |
-
|
| 927 |
],
|
| 928 |
"flags": {},
|
| 929 |
-
"order":
|
| 930 |
"mode": 0,
|
| 931 |
"inputs": [
|
| 932 |
{
|
| 933 |
-
"localized_name": "
|
| 934 |
-
"name": "
|
| 935 |
-
"type": "
|
| 936 |
-
"
|
| 937 |
-
"name": "source_file"
|
| 938 |
-
},
|
| 939 |
-
"link": null
|
| 940 |
-
},
|
| 941 |
-
{
|
| 942 |
-
"localized_name": "load_cap",
|
| 943 |
-
"name": "load_cap",
|
| 944 |
-
"shape": 7,
|
| 945 |
-
"type": "INT",
|
| 946 |
-
"widget": {
|
| 947 |
-
"name": "load_cap"
|
| 948 |
-
},
|
| 949 |
-
"link": null
|
| 950 |
},
|
| 951 |
{
|
| 952 |
-
"localized_name": "
|
| 953 |
-
"name": "
|
| 954 |
"shape": 7,
|
| 955 |
-
"type": "
|
| 956 |
-
"
|
| 957 |
-
"name": "start_index"
|
| 958 |
-
},
|
| 959 |
-
"link": 117
|
| 960 |
},
|
| 961 |
{
|
| 962 |
-
"localized_name": "
|
| 963 |
-
"name": "
|
| 964 |
-
"
|
| 965 |
-
"type": "STRING",
|
| 966 |
"widget": {
|
| 967 |
-
"name": "
|
| 968 |
},
|
| 969 |
"link": null
|
| 970 |
},
|
| 971 |
{
|
| 972 |
-
"localized_name": "
|
| 973 |
-
"name": "
|
| 974 |
"shape": 7,
|
| 975 |
-
"type": "
|
| 976 |
"widget": {
|
| 977 |
-
"name": "
|
| 978 |
},
|
| 979 |
"link": null
|
| 980 |
}
|
| 981 |
],
|
| 982 |
"outputs": [
|
| 983 |
{
|
| 984 |
-
"localized_name": "
|
| 985 |
-
"name": "
|
| 986 |
-
"
|
| 987 |
-
"
|
| 988 |
-
"links": [
|
| 989 |
-
96,
|
| 990 |
-
114
|
| 991 |
-
]
|
| 992 |
-
},
|
| 993 |
-
{
|
| 994 |
-
"localized_name": "character",
|
| 995 |
-
"name": "character",
|
| 996 |
-
"shape": 6,
|
| 997 |
-
"type": "STRING",
|
| 998 |
"links": [
|
| 999 |
-
|
| 1000 |
]
|
| 1001 |
-
},
|
| 1002 |
-
{
|
| 1003 |
-
"localized_name": "count",
|
| 1004 |
-
"name": "count",
|
| 1005 |
-
"type": "INT",
|
| 1006 |
-
"links": null
|
| 1007 |
}
|
| 1008 |
],
|
|
|
|
| 1009 |
"properties": {
|
| 1010 |
-
"
|
| 1011 |
-
"ver": "
|
| 1012 |
-
"Node name for S&R": "
|
| 1013 |
"ue_properties": {
|
| 1014 |
"widget_ue_connectable": {},
|
| 1015 |
-
"
|
| 1016 |
-
"
|
| 1017 |
}
|
| 1018 |
},
|
| 1019 |
"widgets_values": [
|
| 1020 |
-
|
| 1021 |
-
|
| 1022 |
-
0,
|
| 1023 |
-
"",
|
| 1024 |
-
""
|
| 1025 |
]
|
| 1026 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1027 |
{
|
| 1028 |
"id": 64,
|
| 1029 |
"type": "JoyEcho_ModelLoader",
|
|
@@ -1178,15 +922,15 @@
|
|
| 1178 |
}
|
| 1179 |
},
|
| 1180 |
"widgets_values": [
|
| 1181 |
-
"diffusion_models:
|
| 1182 |
-
"",
|
| 1183 |
"text_encoders: gemma3-12b-BASE-clean-Q8_0.gguf",
|
| 1184 |
"",
|
| 1185 |
"(use lora_path / none)",
|
| 1186 |
"",
|
| 1187 |
0,
|
| 1188 |
false,
|
| 1189 |
-
|
| 1190 |
false,
|
| 1191 |
true
|
| 1192 |
]
|
|
@@ -1478,17 +1222,17 @@
|
|
| 1478 |
}
|
| 1479 |
},
|
| 1480 |
"widgets_values": [
|
| 1481 |
-
|
| 1482 |
"randomize",
|
| 1483 |
-
|
| 1484 |
-
|
| 1485 |
-
|
| 1486 |
25,
|
| 1487 |
2,
|
| 1488 |
-
|
| 1489 |
3,
|
| 1490 |
true,
|
| 1491 |
-
|
| 1492 |
true,
|
| 1493 |
"joyecho/shot",
|
| 1494 |
"vhs_glitch",
|
|
@@ -1507,12 +1251,12 @@
|
|
| 1507 |
"id": 58,
|
| 1508 |
"type": "JoyEcho_AutoFinish",
|
| 1509 |
"pos": [
|
| 1510 |
-
|
| 1511 |
99.91012828201144
|
| 1512 |
],
|
| 1513 |
"size": [
|
| 1514 |
328.24765625,
|
| 1515 |
-
|
| 1516 |
],
|
| 1517 |
"flags": {},
|
| 1518 |
"order": 13,
|
|
@@ -1578,6 +1322,16 @@
|
|
| 1578 |
"name": "shots_subdir"
|
| 1579 |
},
|
| 1580 |
"link": null
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1581 |
}
|
| 1582 |
],
|
| 1583 |
"outputs": [
|
|
@@ -1603,10 +1357,267 @@
|
|
| 1603 |
"widgets_values": [
|
| 1604 |
true,
|
| 1605 |
" multishot",
|
| 1606 |
-
1.
|
| 1607 |
"ULTRA",
|
| 1608 |
8,
|
| 1609 |
-
"joyecho"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1610 |
]
|
| 1611 |
}
|
| 1612 |
],
|
|
@@ -1805,10 +1816,10 @@
|
|
| 1805 |
"config": {},
|
| 1806 |
"extra": {
|
| 1807 |
"ds": {
|
| 1808 |
-
"scale": 0.
|
| 1809 |
"offset": [
|
| 1810 |
-
-
|
| 1811 |
-
|
| 1812 |
]
|
| 1813 |
},
|
| 1814 |
"frontendVersion": "1.45.21",
|
|
|
|
| 193 |
}
|
| 194 |
},
|
| 195 |
"widgets_values": [
|
| 196 |
+
"joyecho/PREVIEW",
|
| 197 |
"auto",
|
| 198 |
"auto"
|
| 199 |
]
|
| 200 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 201 |
{
|
| 202 |
"id": 65,
|
| 203 |
"type": "JoyEcho_LoraStacker",
|
|
|
|
| 502 |
},
|
| 503 |
"widgets_values": [
|
| 504 |
"by_seed",
|
| 505 |
+
1444127669,
|
| 506 |
"randomize",
|
| 507 |
"joyecho_refs",
|
| 508 |
"no_reference",
|
|
|
|
| 581 |
}
|
| 582 |
},
|
| 583 |
"widgets_values": [
|
| 584 |
+
"{\n \"prompts\": [\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a locked static medium two-shot at their eye level in a narrow retro arcade aisle, cabinet marquees strobing red, cyan and yellow light across both of them, ID_A on the left and ID_B on the right, standing side by side facing the lens, both faces clear and both mouths fully visible, carpet printed with a wild geometric pattern underfoot. Quiet diegetic sound only: attract-mode jingles chirping from the cabinets, a coin dropping into a tray somewhere down the aisle, and the hum of a dozen CRT screens. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_B is a woman in her early twenties with long jet-black hair with blunt straight bangs, pale matte foundation, deep plum lipstick, a black velvet choker, stacked silver rings on both hands, wearing a long-sleeved black lace top under a charcoal pinafore dress. ID_B's voice is a low, dry, deadpan young American voice, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_B's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_A is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_A's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. ID_B does not speak at any point in this shot; ID_B's mouth stays fully closed and still the whole time, listening. At a quick, natural speed, they stand still side by side; ID_A looks into the lens, the lip movement aligning closely with the audio throughout the line. In a bright, quick voice with a playful edge, ID_A says, \\\"This is my friend. She doesn't smile - that's her whole thing. Two of us now: two faces, two voices, one renderer keeping both straight. Watch us.\\\"\",\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a slow steady push-in to a medium two-shot at their eye level at a bowling alley ball return, lane neon in violet and orange washing over them from behind, ID_B on the left and ID_A on the right leaning against the ball return rack, both faces clear and both mouths fully visible, a rack of marbled house balls in loud colors beside them. Quiet diegetic sound only: a ball rumbling down a distant lane, pins scattering once, and the low drone of the lane machinery. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_B is a woman in her early twenties with long jet-black hair with blunt straight bangs, pale matte foundation, deep plum lipstick, a black velvet choker, stacked silver rings on both hands, wearing a long-sleeved black lace top under a charcoal pinafore dress. ID_B's voice is a low, dry, deadpan young American voice, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_B's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_B is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_B's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. ID_A does not speak at any point in this shot; ID_A's mouth stays fully closed and still the whole time, listening. At an unhurried speed, they hold still; ID_B looks flatly into the lens, the lip movement aligning closely with the audio throughout the line. In a low, dry deadpan, ID_B says, \\\"She talks enough for both of us. Different room, same us. My voice stays down here. Hers stays up there. If either drifts, the trick is dead.\\\"\",\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a locked static medium close-up at her eye level in front of a sunlit graffiti wall, layered tags in electric blue, orange and white behind her, cracked asphalt underfoot, ID_A alone in frame, her head and shoulders filling most of the frame and her mouth fully visible. Quiet diegetic sound only: a skateboard rolling past somewhere off frame, sparrows on a wire, and wind flicking the corner of a peeled poster. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_A is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_A's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. At a quick, natural speed, she stands still against the wall, looking into the lens, the lip movement aligning closely with the audio throughout the line. In a bright, quick voice with a playful edge, ID_A says, \\\"Solo shot. She's fine, she's off being mysterious somewhere. Point is, the room only has to hold one of us right now. Easy mode. Next one's hers.\\\"\",\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a locked static medium close-up at her eye level in a red-lit lounge corner, deep crimson bulbs in wall sconces over wine-dark velvet wallpaper, a single small round table with an unlit candle beside her, ID_B alone in frame, her head and shoulders filling most of the frame and her mouth fully visible, the red light putting hard shine on her black hair. Quiet diegetic sound only: a slow bass line thudding faintly through the wall, glasses clinking once in another room, and the sconce bulbs buzzing softly. ID_B is a woman in her early twenties with long jet-black hair with blunt straight bangs, pale matte foundation, deep plum lipstick, a black velvet choker, stacked silver rings on both hands, wearing a long-sleeved black lace top under a charcoal pinafore dress. ID_B's voice is a low, dry, deadpan young American voice, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_B's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_B is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_B's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. At an unhurried speed, she sits perfectly still, looking flatly into the lens, the lip movement aligning closely with the audio throughout the line. In a low, dry deadpan, ID_B says, \\\"My turn. Notice the voice did not come back wrong. Same low, same flat, same me. Two characters in one memory. That is the actual experiment here.\\\"\",\n \"Consumer camcorder video, 1080p, modest dynamic range, saturated color, slight edge softness: a locked static medium two-shot at their eye level on a neon-lit street corner at night, a wall of layered shop signs in pink, green and blue behind them, wet asphalt throwing colored reflections at the bottom of frame, ID_A on the left with ID_B on the right, both faces clear and both mouths fully visible. Quiet diegetic sound only: a distant siren fading, shoe scuffs on the wet pavement, and the layered hum of the shop signs. ID_A is a woman in her early twenties with a bleached platinum pixie cut with choppy short bangs, a small silver septum ring, a row of small silver hoops up one ear, sharp winged black eyeliner, wearing a battered black leather jacket covered in enamel band pins and safety pins over a ripped neon-pink band tee. ID_A's voice is a bright, quick young American voice with a playful edge, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_A's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_B is a woman in her early twenties with long jet-black hair with blunt straight bangs, pale matte foundation, deep plum lipstick, a black velvet choker, stacked silver rings on both hands, wearing a long-sleeved black lace top under a charcoal pinafore dress. ID_B's voice is a low, dry, deadpan young American voice, casual American accent, casual contractions, captured with close camcorder-microphone proximity. ID_B's mouth stays clearly visible in the frame, and the mouth movement stays naturally synchronized with every spoken line. ID_A is the only person speaking in this shot, the source of the live camcorder dialogue. One continuous line with natural breaths and brief pauses; ID_A's first mouth movement begins with the first audible word, and the mouth settles naturally after the final word. ID_B does not speak at any point in this shot; ID_B's mouth stays fully closed and still the whole time, listening. At a quick, natural speed, they stand still under the signs; ID_A looks into the lens, the lip movement aligning closely with the audio throughout the line. In a bright, quick voice with a playful edge, ID_A says, \\\"Two faces, two voices, five rooms, zero drift. Her deadpan survived. My eyeliner survived. If this works, everything bigger works. Alright - we're out.\\\"\"\n ]\n}"
|
| 585 |
]
|
| 586 |
},
|
| 587 |
{
|
|
|
|
| 613 |
"color": "#432",
|
| 614 |
"bgcolor": "#653"
|
| 615 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 616 |
{
|
| 617 |
"id": 11,
|
| 618 |
"type": "easy seed",
|
|
|
|
| 625 |
106
|
| 626 |
],
|
| 627 |
"flags": {},
|
| 628 |
+
"order": 4,
|
| 629 |
"mode": 0,
|
| 630 |
"inputs": [
|
| 631 |
{
|
|
|
|
| 659 |
}
|
| 660 |
},
|
| 661 |
"widgets_values": [
|
| 662 |
+
0,
|
| 663 |
+
"fixed",
|
| 664 |
null
|
| 665 |
]
|
| 666 |
},
|
| 667 |
{
|
| 668 |
+
"id": 6,
|
| 669 |
+
"type": "CreateVideo",
|
| 670 |
"pos": [
|
| 671 |
+
4328.590366291457,
|
| 672 |
+
359.91012828201144
|
| 673 |
],
|
| 674 |
"size": [
|
| 675 |
+
301.3775449810605,
|
| 676 |
+
102
|
| 677 |
],
|
| 678 |
"flags": {},
|
| 679 |
+
"order": 14,
|
| 680 |
"mode": 0,
|
| 681 |
"inputs": [
|
| 682 |
{
|
| 683 |
+
"localized_name": "images",
|
| 684 |
+
"name": "images",
|
| 685 |
+
"type": "IMAGE",
|
| 686 |
+
"link": 113
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 687 |
},
|
| 688 |
{
|
| 689 |
+
"localized_name": "audio",
|
| 690 |
+
"name": "audio",
|
| 691 |
"shape": 7,
|
| 692 |
+
"type": "AUDIO",
|
| 693 |
+
"link": 108
|
|
|
|
|
|
|
|
|
|
| 694 |
},
|
| 695 |
{
|
| 696 |
+
"localized_name": "fps",
|
| 697 |
+
"name": "fps",
|
| 698 |
+
"type": "FLOAT",
|
|
|
|
| 699 |
"widget": {
|
| 700 |
+
"name": "fps"
|
| 701 |
},
|
| 702 |
"link": null
|
| 703 |
},
|
| 704 |
{
|
| 705 |
+
"localized_name": "bit_depth",
|
| 706 |
+
"name": "bit_depth",
|
| 707 |
"shape": 7,
|
| 708 |
+
"type": "INT",
|
| 709 |
"widget": {
|
| 710 |
+
"name": "bit_depth"
|
| 711 |
},
|
| 712 |
"link": null
|
| 713 |
}
|
| 714 |
],
|
| 715 |
"outputs": [
|
| 716 |
{
|
| 717 |
+
"localized_name": "VIDEO",
|
| 718 |
+
"name": "VIDEO",
|
| 719 |
+
"type": "VIDEO",
|
| 720 |
+
"slot_index": 0,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 721 |
"links": [
|
| 722 |
+
10
|
| 723 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 724 |
}
|
| 725 |
],
|
| 726 |
+
"title": "Create Video (Merge All Shots)",
|
| 727 |
"properties": {
|
| 728 |
+
"cnr_id": "comfy-core",
|
| 729 |
+
"ver": "0.26.2",
|
| 730 |
+
"Node name for S&R": "CreateVideo",
|
| 731 |
"ue_properties": {
|
| 732 |
"widget_ue_connectable": {},
|
| 733 |
+
"version": "7.8",
|
| 734 |
+
"input_ue_unconnectable": {}
|
| 735 |
}
|
| 736 |
},
|
| 737 |
"widgets_values": [
|
| 738 |
+
25,
|
| 739 |
+
8
|
|
|
|
|
|
|
|
|
|
| 740 |
]
|
| 741 |
},
|
| 742 |
+
{
|
| 743 |
+
"id": 60,
|
| 744 |
+
"type": "Note",
|
| 745 |
+
"pos": [
|
| 746 |
+
2780.2351442980976,
|
| 747 |
+
806.7950609883953
|
| 748 |
+
],
|
| 749 |
+
"size": [
|
| 750 |
+
1057.751230034948,
|
| 751 |
+
248.99507986020944
|
| 752 |
+
],
|
| 753 |
+
"flags": {},
|
| 754 |
+
"order": 5,
|
| 755 |
+
"mode": 0,
|
| 756 |
+
"inputs": [],
|
| 757 |
+
"outputs": [],
|
| 758 |
+
"properties": {
|
| 759 |
+
"ue_properties": {
|
| 760 |
+
"widget_ue_connectable": {},
|
| 761 |
+
"version": "7.8",
|
| 762 |
+
"input_ue_unconnectable": {}
|
| 763 |
+
}
|
| 764 |
+
},
|
| 765 |
+
"widgets_values": [
|
| 766 |
+
"MODEL LOADER - what to set, what to leave\n------------------------------------------------\nSET THESE TWO:\n* model_file - the DiT checkpoint. fp8 build (23 GB) for 24 GB cards; bf16 (43 GB) for 32 GB+ (needs sequential offload).\n* gemma_file - your Gemma-3-12B text encoder, picked from models/text_encoders or models/clip. Single-file .safetensors or .gguf. A GGUF encoder is the light option (fits 24 GB systems easily).\n\nLEAVE ALONE UNLESS YOU KNOW WHY:\n* checkpoint_path - only needed when model_file is a .gguf (GGUF = DiT only; this must then point at a full safetensors to supply the VAEs + vocoder).\n* gemma_path - only for an HF gemma-3-12b-it DIRECTORY (dropdowns list files, not folders).\n* lora_file / lora_path - optional style LoRA. Ignored for GGUF DiTs.\n\nVRAM GUIDE:\n* 24 GB: fp8 model_file + low_vram ON (encoder runs on CPU; the encode is cached per prompt, so it only costs once).\n* 32 GB: bf16 model_file if downloaded; low_vram still recommended (the bf16 encoder alone is ~23 GB).\n* RTX 40/50-series: turn fp8_scaled_mm ON - native fp8 matmul, real speedup, and at moderate resolutions the DiT can run with sequential_offload OFF. Older GPUs: leave it off.\n* encoder_fp8 - halves encoder memory at a slight embedding shift (voice quality is the canary). Try it if RAM-starved."
|
| 767 |
+
],
|
| 768 |
+
"color": "#432",
|
| 769 |
+
"bgcolor": "#653"
|
| 770 |
+
},
|
| 771 |
{
|
| 772 |
"id": 64,
|
| 773 |
"type": "JoyEcho_ModelLoader",
|
|
|
|
| 922 |
}
|
| 923 |
},
|
| 924 |
"widgets_values": [
|
| 925 |
+
"diffusion_models: LTX23-echoVid-ltxAud-Surgical-DiT-Q8_0.gguf",
|
| 926 |
+
"F:\\ComfyUI_windows_portable_nvidia\\ComfyUI_windows_portable\\ComfyUI\\models\\diffusion_models\\ltx23_echoVid-ltxAud_surgical_bf16.safetensors",
|
| 927 |
"text_encoders: gemma3-12b-BASE-clean-Q8_0.gguf",
|
| 928 |
"",
|
| 929 |
"(use lora_path / none)",
|
| 930 |
"",
|
| 931 |
0,
|
| 932 |
false,
|
| 933 |
+
false,
|
| 934 |
false,
|
| 935 |
true
|
| 936 |
]
|
|
|
|
| 1222 |
}
|
| 1223 |
},
|
| 1224 |
"widgets_values": [
|
| 1225 |
+
1274354006,
|
| 1226 |
"randomize",
|
| 1227 |
+
361,
|
| 1228 |
+
736,
|
| 1229 |
+
1280,
|
| 1230 |
25,
|
| 1231 |
2,
|
| 1232 |
+
7,
|
| 1233 |
3,
|
| 1234 |
true,
|
| 1235 |
+
96,
|
| 1236 |
true,
|
| 1237 |
"joyecho/shot",
|
| 1238 |
"vhs_glitch",
|
|
|
|
| 1251 |
"id": 58,
|
| 1252 |
"type": "JoyEcho_AutoFinish",
|
| 1253 |
"pos": [
|
| 1254 |
+
4329.297195655411,
|
| 1255 |
99.91012828201144
|
| 1256 |
],
|
| 1257 |
"size": [
|
| 1258 |
328.24765625,
|
| 1259 |
+
202
|
| 1260 |
],
|
| 1261 |
"flags": {},
|
| 1262 |
"order": 13,
|
|
|
|
| 1322 |
"name": "shots_subdir"
|
| 1323 |
},
|
| 1324 |
"link": null
|
| 1325 |
+
},
|
| 1326 |
+
{
|
| 1327 |
+
"localized_name": "upscale_mode",
|
| 1328 |
+
"name": "upscale_mode",
|
| 1329 |
+
"shape": 7,
|
| 1330 |
+
"type": "COMBO",
|
| 1331 |
+
"widget": {
|
| 1332 |
+
"name": "upscale_mode"
|
| 1333 |
+
},
|
| 1334 |
+
"link": null
|
| 1335 |
}
|
| 1336 |
],
|
| 1337 |
"outputs": [
|
|
|
|
| 1357 |
"widgets_values": [
|
| 1358 |
true,
|
| 1359 |
" multishot",
|
| 1360 |
+
1.5,
|
| 1361 |
"ULTRA",
|
| 1362 |
8,
|
| 1363 |
+
"joyecho",
|
| 1364 |
+
"bicubic+cas (deterministic)"
|
| 1365 |
+
]
|
| 1366 |
+
},
|
| 1367 |
+
{
|
| 1368 |
+
"id": 52,
|
| 1369 |
+
"type": "JoyEcho_PromptSource",
|
| 1370 |
+
"pos": [
|
| 1371 |
+
1.3774104683194017,
|
| 1372 |
+
286
|
| 1373 |
+
],
|
| 1374 |
+
"size": [
|
| 1375 |
+
724.5169729521541,
|
| 1376 |
+
201.68048280657888
|
| 1377 |
+
],
|
| 1378 |
+
"flags": {},
|
| 1379 |
+
"order": 7,
|
| 1380 |
+
"mode": 0,
|
| 1381 |
+
"inputs": [
|
| 1382 |
+
{
|
| 1383 |
+
"localized_name": "source_file",
|
| 1384 |
+
"name": "source_file",
|
| 1385 |
+
"type": "COMBO",
|
| 1386 |
+
"widget": {
|
| 1387 |
+
"name": "source_file"
|
| 1388 |
+
},
|
| 1389 |
+
"link": null
|
| 1390 |
+
},
|
| 1391 |
+
{
|
| 1392 |
+
"localized_name": "load_cap",
|
| 1393 |
+
"name": "load_cap",
|
| 1394 |
+
"shape": 7,
|
| 1395 |
+
"type": "INT",
|
| 1396 |
+
"widget": {
|
| 1397 |
+
"name": "load_cap"
|
| 1398 |
+
},
|
| 1399 |
+
"link": null
|
| 1400 |
+
},
|
| 1401 |
+
{
|
| 1402 |
+
"localized_name": "start_index",
|
| 1403 |
+
"name": "start_index",
|
| 1404 |
+
"shape": 7,
|
| 1405 |
+
"type": "INT",
|
| 1406 |
+
"widget": {
|
| 1407 |
+
"name": "start_index"
|
| 1408 |
+
},
|
| 1409 |
+
"link": 117
|
| 1410 |
+
},
|
| 1411 |
+
{
|
| 1412 |
+
"localized_name": "character_override",
|
| 1413 |
+
"name": "character_override",
|
| 1414 |
+
"shape": 7,
|
| 1415 |
+
"type": "STRING",
|
| 1416 |
+
"widget": {
|
| 1417 |
+
"name": "character_override"
|
| 1418 |
+
},
|
| 1419 |
+
"link": null
|
| 1420 |
+
},
|
| 1421 |
+
{
|
| 1422 |
+
"localized_name": "manual_path",
|
| 1423 |
+
"name": "manual_path",
|
| 1424 |
+
"shape": 7,
|
| 1425 |
+
"type": "STRING",
|
| 1426 |
+
"widget": {
|
| 1427 |
+
"name": "manual_path"
|
| 1428 |
+
},
|
| 1429 |
+
"link": null
|
| 1430 |
+
}
|
| 1431 |
+
],
|
| 1432 |
+
"outputs": [
|
| 1433 |
+
{
|
| 1434 |
+
"localized_name": "story_idea",
|
| 1435 |
+
"name": "story_idea",
|
| 1436 |
+
"shape": 6,
|
| 1437 |
+
"type": "STRING",
|
| 1438 |
+
"links": [
|
| 1439 |
+
96,
|
| 1440 |
+
114
|
| 1441 |
+
]
|
| 1442 |
+
},
|
| 1443 |
+
{
|
| 1444 |
+
"localized_name": "character",
|
| 1445 |
+
"name": "character",
|
| 1446 |
+
"shape": 6,
|
| 1447 |
+
"type": "STRING",
|
| 1448 |
+
"links": [
|
| 1449 |
+
100
|
| 1450 |
+
]
|
| 1451 |
+
},
|
| 1452 |
+
{
|
| 1453 |
+
"localized_name": "count",
|
| 1454 |
+
"name": "count",
|
| 1455 |
+
"type": "INT",
|
| 1456 |
+
"links": null
|
| 1457 |
+
}
|
| 1458 |
+
],
|
| 1459 |
+
"properties": {
|
| 1460 |
+
"aux_id": "RealRebelAI/ComfyUI_JoyAI_Echo_GGUF_Nodes",
|
| 1461 |
+
"ver": "0d9e32fcd2d255a16604368fcaa1875c380c7f3b",
|
| 1462 |
+
"Node name for S&R": "JoyEcho_PromptSource",
|
| 1463 |
+
"ue_properties": {
|
| 1464 |
+
"widget_ue_connectable": {},
|
| 1465 |
+
"input_ue_unconnectable": {},
|
| 1466 |
+
"version": "7.8"
|
| 1467 |
+
}
|
| 1468 |
+
},
|
| 1469 |
+
"widgets_values": [
|
| 1470 |
+
"JSON: THE_DOUBLE_BILL_PUNK_GOTH_JOYECHO.json",
|
| 1471 |
+
1,
|
| 1472 |
+
0,
|
| 1473 |
+
"",
|
| 1474 |
+
""
|
| 1475 |
+
]
|
| 1476 |
+
},
|
| 1477 |
+
{
|
| 1478 |
+
"id": 59,
|
| 1479 |
+
"type": "JoyEcho_LLMEnhance",
|
| 1480 |
+
"pos": [
|
| 1481 |
+
900,
|
| 1482 |
+
100
|
| 1483 |
+
],
|
| 1484 |
+
"size": [
|
| 1485 |
+
1161.0279043079718,
|
| 1486 |
+
736.9512031915835
|
| 1487 |
+
],
|
| 1488 |
+
"flags": {},
|
| 1489 |
+
"order": 8,
|
| 1490 |
+
"mode": 0,
|
| 1491 |
+
"inputs": [
|
| 1492 |
+
{
|
| 1493 |
+
"localized_name": "story_idea",
|
| 1494 |
+
"name": "story_idea",
|
| 1495 |
+
"type": "STRING",
|
| 1496 |
+
"widget": {
|
| 1497 |
+
"name": "story_idea"
|
| 1498 |
+
},
|
| 1499 |
+
"link": 114
|
| 1500 |
+
},
|
| 1501 |
+
{
|
| 1502 |
+
"localized_name": "mode",
|
| 1503 |
+
"name": "mode",
|
| 1504 |
+
"type": "COMBO",
|
| 1505 |
+
"widget": {
|
| 1506 |
+
"name": "mode"
|
| 1507 |
+
},
|
| 1508 |
+
"link": null
|
| 1509 |
+
},
|
| 1510 |
+
{
|
| 1511 |
+
"localized_name": "api_key",
|
| 1512 |
+
"name": "api_key",
|
| 1513 |
+
"type": "STRING",
|
| 1514 |
+
"widget": {
|
| 1515 |
+
"name": "api_key"
|
| 1516 |
+
},
|
| 1517 |
+
"link": null
|
| 1518 |
+
},
|
| 1519 |
+
{
|
| 1520 |
+
"localized_name": "system_prompt",
|
| 1521 |
+
"name": "system_prompt",
|
| 1522 |
+
"type": "STRING",
|
| 1523 |
+
"widget": {
|
| 1524 |
+
"name": "system_prompt"
|
| 1525 |
+
},
|
| 1526 |
+
"link": null
|
| 1527 |
+
},
|
| 1528 |
+
{
|
| 1529 |
+
"localized_name": "base_url",
|
| 1530 |
+
"name": "base_url",
|
| 1531 |
+
"shape": 7,
|
| 1532 |
+
"type": "STRING",
|
| 1533 |
+
"widget": {
|
| 1534 |
+
"name": "base_url"
|
| 1535 |
+
},
|
| 1536 |
+
"link": null
|
| 1537 |
+
},
|
| 1538 |
+
{
|
| 1539 |
+
"localized_name": "model_name",
|
| 1540 |
+
"name": "model_name",
|
| 1541 |
+
"shape": 7,
|
| 1542 |
+
"type": "STRING",
|
| 1543 |
+
"widget": {
|
| 1544 |
+
"name": "model_name"
|
| 1545 |
+
},
|
| 1546 |
+
"link": null
|
| 1547 |
+
},
|
| 1548 |
+
{
|
| 1549 |
+
"localized_name": "num_shots",
|
| 1550 |
+
"name": "num_shots",
|
| 1551 |
+
"shape": 7,
|
| 1552 |
+
"type": "INT",
|
| 1553 |
+
"widget": {
|
| 1554 |
+
"name": "num_shots"
|
| 1555 |
+
},
|
| 1556 |
+
"link": null
|
| 1557 |
+
},
|
| 1558 |
+
{
|
| 1559 |
+
"localized_name": "temperature",
|
| 1560 |
+
"name": "temperature",
|
| 1561 |
+
"shape": 7,
|
| 1562 |
+
"type": "FLOAT",
|
| 1563 |
+
"widget": {
|
| 1564 |
+
"name": "temperature"
|
| 1565 |
+
},
|
| 1566 |
+
"link": null
|
| 1567 |
+
},
|
| 1568 |
+
{
|
| 1569 |
+
"localized_name": "num_frames",
|
| 1570 |
+
"name": "num_frames",
|
| 1571 |
+
"shape": 7,
|
| 1572 |
+
"type": "INT",
|
| 1573 |
+
"widget": {
|
| 1574 |
+
"name": "num_frames"
|
| 1575 |
+
},
|
| 1576 |
+
"link": null
|
| 1577 |
+
},
|
| 1578 |
+
{
|
| 1579 |
+
"localized_name": "fps",
|
| 1580 |
+
"name": "fps",
|
| 1581 |
+
"shape": 7,
|
| 1582 |
+
"type": "FLOAT",
|
| 1583 |
+
"widget": {
|
| 1584 |
+
"name": "fps"
|
| 1585 |
+
},
|
| 1586 |
+
"link": null
|
| 1587 |
+
}
|
| 1588 |
+
],
|
| 1589 |
+
"outputs": [
|
| 1590 |
+
{
|
| 1591 |
+
"localized_name": "prompts_json",
|
| 1592 |
+
"name": "prompts_json",
|
| 1593 |
+
"type": "STRING",
|
| 1594 |
+
"links": [
|
| 1595 |
+
115,
|
| 1596 |
+
116
|
| 1597 |
+
]
|
| 1598 |
+
}
|
| 1599 |
+
],
|
| 1600 |
+
"properties": {
|
| 1601 |
+
"aux_id": "RealRebelAI/ComfyUI_JoyAI_Echo_GGUF_Nodes",
|
| 1602 |
+
"ver": "0d9e32fcd2d255a16604368fcaa1875c380c7f3b",
|
| 1603 |
+
"Node name for S&R": "JoyEcho_LLMEnhance",
|
| 1604 |
+
"ue_properties": {
|
| 1605 |
+
"widget_ue_connectable": {},
|
| 1606 |
+
"input_ue_unconnectable": {},
|
| 1607 |
+
"version": "7.8"
|
| 1608 |
+
}
|
| 1609 |
+
},
|
| 1610 |
+
"widgets_values": [
|
| 1611 |
+
"",
|
| 1612 |
+
"passthrough (raw JSON, skip LLM)",
|
| 1613 |
+
"",
|
| 1614 |
+
"",
|
| 1615 |
+
"http://localhost:11434/v1",
|
| 1616 |
+
"glm-5.2:cloud",
|
| 1617 |
+
0,
|
| 1618 |
+
0.7,
|
| 1619 |
+
361,
|
| 1620 |
+
25
|
| 1621 |
]
|
| 1622 |
}
|
| 1623 |
],
|
|
|
|
| 1816 |
"config": {},
|
| 1817 |
"extra": {
|
| 1818 |
"ds": {
|
| 1819 |
+
"scale": 0.7260000000000874,
|
| 1820 |
"offset": [
|
| 1821 |
+
-1323.7145260311115,
|
| 1822 |
+
519.5332970752396
|
| 1823 |
]
|
| 1824 |
},
|
| 1825 |
"frontendVersion": "1.45.21",
|