Spaces:
Running on Zero
Running on Zero
Revise spec: LTX-2.3 22B distilled via diffusers, ZeroGPU H200, optional 2x upscale toggle
Browse files
docs/superpowers/specs/2026-06-25-ltx-image-to-video-space-design.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# LTX Image-to-Video Gradio Space β Design
|
| 2 |
|
| 3 |
**Date:** 2026-06-25
|
| 4 |
**Status:** Approved
|
|
@@ -6,90 +6,133 @@
|
|
| 6 |
|
| 7 |
## Goal
|
| 8 |
|
| 9 |
-
A
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
| 12 |
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
## Decisions (from brainstorming)
|
| 19 |
|
| 20 |
| Question | Decision |
|
| 21 |
|----------|----------|
|
| 22 |
-
| Relationship to ComfyUI repo | Native Gradio app
|
| 23 |
-
| Model
|
| 24 |
-
|
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
## Architecture
|
| 28 |
|
| 29 |
-
Single `app.py` with one Gradio `Blocks` UI. The pipeline
|
| 30 |
-
at module import;
|
| 31 |
-
function that moves work to the GPU.
|
| 32 |
|
| 33 |
```
|
| 34 |
app.py
|
| 35 |
-
ββ load
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
| 40 |
```
|
| 41 |
|
| 42 |
-
## Component
|
| 43 |
|
| 44 |
-
###
|
| 45 |
-
-
|
| 46 |
-
|
| 47 |
-
-
|
| 48 |
-
-
|
| 49 |
-
|
|
|
|
| 50 |
|
| 51 |
### Fixed defaults (hidden from the user)
|
| 52 |
-
- Resolution:
|
| 53 |
-
each dimension rounded to a multiple of 32
|
| 54 |
-
-
|
| 55 |
-
-
|
| 56 |
-
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
-
|
| 61 |
-
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
|
| 65 |
### UI (`gr.Blocks`)
|
| 66 |
- `gr.Image(type="pil")` β input image.
|
| 67 |
- `gr.Textbox` β prompt.
|
| 68 |
-
- `gr.
|
| 69 |
-
- `gr.
|
| 70 |
-
-
|
| 71 |
-
|
| 72 |
|
| 73 |
-
## Error
|
| 74 |
- Empty image or empty prompt β `gr.Warning`, no generation run.
|
| 75 |
-
- Pipeline / OOM / runtime exception β caught and surfaced as a
|
| 76 |
-
with a short human-readable message
|
|
|
|
|
|
|
| 77 |
|
| 78 |
-
## Out of
|
| 79 |
-
-
|
| 80 |
-
-
|
| 81 |
-
-
|
| 82 |
-
ComfyUI project's scope, not this minimal demo.
|
| 83 |
|
| 84 |
## Testing
|
| 85 |
- Diffusion output is not meaningfully unit-testable.
|
| 86 |
- Validation:
|
| 87 |
-
- A `generate()` smoke path with a mocked pipeline (
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
- Manual run on the deployed Space to confirm end-to-end behavior
|
|
|
|
| 91 |
|
| 92 |
-
## Files
|
| 93 |
- `app.py` (new) β the entire application.
|
| 94 |
- `requirements.txt` (new) β Python dependencies.
|
| 95 |
- `README.md` (existing) β unchanged; HF Space frontmatter preserved.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# LTX-2.3 Image-to-Video Gradio Space β Design
|
| 2 |
|
| 3 |
**Date:** 2026-06-25
|
| 4 |
**Status:** Approved
|
|
|
|
| 6 |
|
| 7 |
## Goal
|
| 8 |
|
| 9 |
+
A Hugging Face Space where a user uploads an image and types a prompt, clicks
|
| 10 |
+
**Generate**, and receives a short MP4 video (with audio). It matches the model
|
| 11 |
+
stack used by the `WhatDreamsCost/WhatDreamsCost-ComfyUI` "LTX Director 2"
|
| 12 |
+
workflow, reimplemented as a native Gradio app using **`diffusers`** β not
|
| 13 |
+
ComfyUI.
|
| 14 |
|
| 15 |
+
## Reference workflow
|
| 16 |
+
|
| 17 |
+
Derived from `docs/LTX_Director_2_Workflow_Hotfix.json`. The relevant model
|
| 18 |
+
stack and sampler settings from that graph:
|
| 19 |
+
|
| 20 |
+
| Component | Workflow value |
|
| 21 |
+
|-----------|----------------|
|
| 22 |
+
| Transformer | `ltx-2.3-22b-distilled` (22B distilled, fp8 in the Comfy graph) |
|
| 23 |
+
| Text encoder | Gemma-3-12B (`gemma_3_12B_it`) + LTX text projection |
|
| 24 |
+
| Video VAE | `LTX23_video_vae_bf16` |
|
| 25 |
+
| Audio VAE | `LTX23_audio_vae_bf16` (LTX-2.3 jointly generates audio + video) |
|
| 26 |
+
| Spatial upscaler | `ltx-2.3-spatial-upscaler-x2-1.1` (optional 2nd stage) |
|
| 27 |
+
| Sampler / schedule | euler, linear_quadratic, **8 steps**, **CFG = 1** |
|
| 28 |
+
| Output | **24 fps, 5 s, 120 frames**, two-stage (base β 2Γ upscale) |
|
| 29 |
|
| 30 |
## Decisions (from brainstorming)
|
| 31 |
|
| 32 |
| Question | Decision |
|
| 33 |
|----------|----------|
|
| 34 |
+
| Relationship to ComfyUI repo | Native Gradio app via `diffusers` (not ComfyUI) |
|
| 35 |
+
| Model | **LTX-2.3 22B distilled** (matches the workflow) |
|
| 36 |
+
| Inference library | `diffusers` LTX-2.3 distilled image-to-video pipeline |
|
| 37 |
+
| Hardware | **ZeroGPU** (H200, 70 GB) via `@spaces.GPU` |
|
| 38 |
+
| UI scope | Minimal: image + prompt + Generate, plus one "2Γ upscale" toggle |
|
| 39 |
+
| Audio | Included (LTX-2.3 generates A/V jointly) |
|
| 40 |
+
| 2Γ upscale stage | Optional UI toggle, **default OFF** (time-budget safety) |
|
| 41 |
+
|
| 42 |
+
## Feasibility (verified)
|
| 43 |
+
|
| 44 |
+
- **Inference path:** `diffusers` natively supports LTX-2.3. Use
|
| 45 |
+
`diffusers/LTX-2.3-Distilled-Diffusers` (8 steps, CFG = 1) with the
|
| 46 |
+
image-to-video / IC-LoRA pipeline and the optional two-stage
|
| 47 |
+
generateβupscale recipe. No ComfyUI fp8 safetensors or custom loaders
|
| 48 |
+
required.
|
| 49 |
+
- **VRAM:** ZeroGPU runs on H200 with 70 GB. The 22B distilled is ~46 GB in
|
| 50 |
+
bf16, ~23 GB in fp8; fits in 70 GB alongside Gemma-3-12B with
|
| 51 |
+
`enable_model_cpu_offload()`.
|
| 52 |
+
- **GPU time budget (the real constraint):** ZeroGPU defaults to 60 s per
|
| 53 |
+
call, raised with `@spaces.GPU(duration=...)`, with a hard ceiling and a
|
| 54 |
+
daily quota (longer durations favor PRO). The base 120-frame generation is
|
| 55 |
+
the safe default; the 2Γ upscale stage is the slow part and is therefore an
|
| 56 |
+
opt-in toggle, default OFF.
|
| 57 |
|
| 58 |
## Architecture
|
| 59 |
|
| 60 |
+
Single `app.py` with one Gradio `Blocks` UI. The pipeline(s) are constructed
|
| 61 |
+
once at module import; generation runs inside a ZeroGPU-decorated worker.
|
|
|
|
| 62 |
|
| 63 |
```
|
| 64 |
app.py
|
| 65 |
+
ββ load diffusers LTX-2.3 distilled pipeline(s) at import
|
| 66 |
+
β β’ base image-to-video pipeline (8 steps, CFG=1)
|
| 67 |
+
β β’ spatial 2x upscale pipeline (loaded lazily / only used when toggled)
|
| 68 |
+
β β’ enable_model_cpu_offload() to fit 70 GB
|
| 69 |
+
ββ @spaces.GPU(duration=...) generate(image, prompt, upscale) -> mp4 path
|
| 70 |
+
ββ gr.Blocks UI: Image + Prompt + Upscale checkbox + Generate -> Video
|
| 71 |
+
requirements.txt (diffusers, transformers, torch, spaces, imageio[ffmpeg], ...)
|
| 72 |
+
README.md (existing; HF Space frontmatter preserved)
|
| 73 |
```
|
| 74 |
|
| 75 |
+
## Component details
|
| 76 |
|
| 77 |
+
### Models (`diffusers`)
|
| 78 |
+
- LTX-2.3 22B distilled image-to-video pipeline, fp8 where available.
|
| 79 |
+
- Gemma-3-12B text encoder (loaded by the pipeline).
|
| 80 |
+
- Optional `ltx-2.3-spatial-upscaler-x2` pipeline for the 2Γ stage.
|
| 81 |
+
- `enable_model_cpu_offload()` to stay within 70 GB.
|
| 82 |
+
- Loaded once at module import. GPU placement happens inside the ZeroGPU
|
| 83 |
+
worker (ZeroGPU attaches the GPU only during the decorated call).
|
| 84 |
|
| 85 |
### Fixed defaults (hidden from the user)
|
| 86 |
+
- Resolution: base resolution per the LTX-2.3 distilled recipe, auto-fit to the
|
| 87 |
+
uploaded image's aspect ratio, each dimension rounded to a multiple of 32.
|
| 88 |
+
- Frames / fps: **120 frames @ 24 fps (~5 s)**.
|
| 89 |
+
- Steps: **8** (distilled). Guidance: **CFG = 1**. Schedule: linear-quadratic.
|
| 90 |
+
- Seed: random each run.
|
| 91 |
+
|
| 92 |
+
### `generate(image, prompt, upscale)`
|
| 93 |
+
- Decorated with `@spaces.GPU(duration=...)` (set near the ZeroGPU ceiling).
|
| 94 |
+
- Steps: validate inputs β preprocess/resize image to target dims β run base
|
| 95 |
+
image-to-video pipeline β if `upscale` is True, run the 2Γ spatial-upscale
|
| 96 |
+
stage β mux generated audio β export to MP4 (`imageio` / ffmpeg) β return the
|
| 97 |
+
file path for `gr.Video`.
|
| 98 |
|
| 99 |
### UI (`gr.Blocks`)
|
| 100 |
- `gr.Image(type="pil")` β input image.
|
| 101 |
- `gr.Textbox` β prompt.
|
| 102 |
+
- `gr.Checkbox("2Γ high-res upscale", value=False)` β opt-in upscale stage.
|
| 103 |
+
- `gr.Button("Generate")`.
|
| 104 |
+
- `gr.Video` β output (MP4 with audio).
|
| 105 |
+
- Optional: 1β2 `gr.Examples` rows (image + prompt) if assets are available.
|
| 106 |
|
| 107 |
+
## Error handling
|
| 108 |
- Empty image or empty prompt β `gr.Warning`, no generation run.
|
| 109 |
+
- Pipeline / OOM / time-limit / runtime exception β caught and surfaced as a
|
| 110 |
+
`gr.Error` with a short human-readable message so the worker does not crash.
|
| 111 |
+
If the upscale stage is the cause, the message suggests retrying with the
|
| 112 |
+
toggle off.
|
| 113 |
|
| 114 |
+
## Out of scope (YAGNI)
|
| 115 |
+
- ComfyUI runtime, custom nodes, node graph, the timeline / Director UI.
|
| 116 |
+
- Video editing, keyframes, retake mode, IC-LoRA style transfer, prompt relay.
|
| 117 |
+
- Negative prompt, extra sliders, manual seed entry, resolution controls.
|
|
|
|
| 118 |
|
| 119 |
## Testing
|
| 120 |
- Diffusion output is not meaningfully unit-testable.
|
| 121 |
- Validation:
|
| 122 |
+
- A `generate()` smoke path with a mocked pipeline (dummy frames) confirming
|
| 123 |
+
an MP4 is written and a valid path returned, that empty-input guards fire,
|
| 124 |
+
and that the `upscale` flag selects the right code path.
|
| 125 |
+
- Manual run on the deployed Space to confirm end-to-end behavior, VRAM fit,
|
| 126 |
+
and that the default (no-upscale) path stays within the ZeroGPU time limit.
|
| 127 |
|
| 128 |
+
## Files touched
|
| 129 |
- `app.py` (new) β the entire application.
|
| 130 |
- `requirements.txt` (new) β Python dependencies.
|
| 131 |
- `README.md` (existing) β unchanged; HF Space frontmatter preserved.
|
| 132 |
+
|
| 133 |
+
## References
|
| 134 |
+
- diffusers LTX-2.3: https://huggingface.co/diffusers/LTX-2.3-Diffusers
|
| 135 |
+
- diffusers LTX-2.3 distilled: https://huggingface.co/diffusers/LTX-2.3-Distilled-Diffusers
|
| 136 |
+
- Lightricks LTX-2.3 weights: https://huggingface.co/Lightricks/LTX-2.3
|
| 137 |
+
- Lightricks LTX-2 inference: https://github.com/Lightricks/LTX-2
|
| 138 |
+
- ZeroGPU docs: https://huggingface.co/docs/hub/en/spaces-zerogpu
|