Instructions to use PrunaAI/PrunaVAED with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use PrunaAI/PrunaVAED with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("PrunaAI/PrunaVAED", torch_dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - LTX.io
How to use PrunaAI/PrunaVAED with LTX.io:
# Install the LTX-2 pipelines git clone https://github.com/Lightricks/LTX-2.git cd LTX-2 uv sync --frozen
# Download the weights from this repo, plus the Gemma text encoder hf download PrunaAI/PrunaVAED --local-dir models/PrunaVAED hf download google/gemma-3-12b-it-qat-q4_0-unquantized --local-dir models/gemma-3-12b
# Fast pipeline (distilled model, no distilled LoRA needed) uv run python -m ltx_pipelines.distilled \ --distilled-checkpoint-path models/PrunaVAED/<distilled-checkpoint>.safetensors \ --spatial-upsampler-path models/PrunaVAED/<spatial-upsampler>.safetensors \ --gemma-root models/gemma-3-12b \ --prompt "A beautiful sunset over the ocean" \ --output-path output.mp4 # For image-to-video, add: --image path/to/image.jpg 0 0.8# HQ pipeline (two-stage, higher quality) uv run python -m ltx_pipelines.ti2vid_two_stages_hq \ --checkpoint-path models/PrunaVAED/<checkpoint>.safetensors \ --distilled-lora models/PrunaVAED/<distilled-lora>.safetensors 0.8 \ --spatial-upsampler-path models/PrunaVAED/<spatial-upsampler>.safetensors \ --gemma-root models/gemma-3-12b \ --prompt "A beautiful sunset over the ocean" \ --output-path output.mp4 # For image-to-video, add: --image path/to/image.jpg 0 0.8 - Notebooks
- Google Colab
- Kaggle
Commit ·
e9932d5
0
Parent(s):
Duplicate from mehdiPrunaAI/LTX2_3_PrunedDecoder
Browse files- .gitattributes +55 -0
- README.md +212 -0
- example/student/04MhZs7YN08-Scene-0048.mp4 +3 -0
- example/student/7y57zc-GvBA-Scene-0009.mp4 +3 -0
- example/student/8YSha7iU2ZI-Scene-1025.mp4 +3 -0
- example/student/97moBezrzLo-Scene-0076.mp4 +3 -0
- example/student/9GDE5-rOOfk-Scene-0010.mp4 +3 -0
- example/student/DZt-RtpcJZQ-Scene-0043_m2.mp4 +3 -0
- example/student/FAfMSWi0FSA-Scene-0200.mp4 +3 -0
- example/student/a5M8hWgQbjU-Scene-0191.mp4 +3 -0
- example/student/ijGuAu0lLNM-Scene-0008.mp4 +3 -0
- example/student/zFehFw9SbDw-Scene-0034.mp4 +3 -0
- example/teacher/04MhZs7YN08-Scene-0048.mp4 +3 -0
- example/teacher/7y57zc-GvBA-Scene-0009.mp4 +3 -0
- example/teacher/8YSha7iU2ZI-Scene-1025.mp4 +3 -0
- example/teacher/97moBezrzLo-Scene-0076.mp4 +3 -0
- example/teacher/9GDE5-rOOfk-Scene-0010.mp4 +3 -0
- example/teacher/DZt-RtpcJZQ-Scene-0043_teacher.mp4 +3 -0
- example/teacher/FAfMSWi0FSA-Scene-0200.mp4 +3 -0
- example/teacher/a5M8hWgQbjU-Scene-0191.mp4 +3 -0
- example/teacher/ijGuAu0lLNM-Scene-0008.mp4 +3 -0
- example/teacher/zFehFw9SbDw-Scene-0034.mp4 +3 -0
- patch_diffusers.py +219 -0
- requirements-test.txt +19 -0
- tests/test_distilled_decode.py +223 -0
- vae/config.json +96 -0
- vae/diffusion_pytorch_model.safetensors +3 -0
.gitattributes
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
example/student/04MhZs7YN08-Scene-0048.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
example/student/7y57zc-GvBA-Scene-0009.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
example/student/8YSha7iU2ZI-Scene-1025.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
example/student/97moBezrzLo-Scene-0076.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
example/student/9GDE5-rOOfk-Scene-0010.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
example/student/a5M8hWgQbjU-Scene-0191.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
example/student/DZt-RtpcJZQ-Scene-0043_m2.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
example/student/FAfMSWi0FSA-Scene-0200.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
example/student/ijGuAu0lLNM-Scene-0008.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
example/student/zFehFw9SbDw-Scene-0034.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
example/teacher/04MhZs7YN08-Scene-0048.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
example/teacher/7y57zc-GvBA-Scene-0009.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
example/teacher/8YSha7iU2ZI-Scene-1025.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
example/teacher/97moBezrzLo-Scene-0076.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
example/teacher/9GDE5-rOOfk-Scene-0010.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
example/teacher/a5M8hWgQbjU-Scene-0191.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
example/teacher/DZt-RtpcJZQ-Scene-0043_teacher.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
example/teacher/FAfMSWi0FSA-Scene-0200.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
example/teacher/ijGuAu0lLNM-Scene-0008.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
example/teacher/zFehFw9SbDw-Scene-0034.mp4 filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
base_model:
|
| 3 |
+
- Lightricks/LTX-2.3
|
| 4 |
+
pipeline_tag: text-to-video
|
| 5 |
+
---
|
| 6 |
+
<!-- header start -->
|
| 7 |
+
<!-- 200823 -->
|
| 8 |
+
<div style="width: auto; margin-left: auto; margin-right: auto">
|
| 9 |
+
<a href="https://docs.pruna.ai/en/latest/setup/pip.html" target="_blank" rel="noopener noreferrer">
|
| 10 |
+
<img src="https://imgur.com/rVAgqMY.png" alt="PrunaAI" style="width: 100%; min-width: 400px; display: block; margin: auto;">
|
| 11 |
+
</a>
|
| 12 |
+
</div>
|
| 13 |
+
<!-- header end -->
|
| 14 |
+
|
| 15 |
+
[](https://github.com/PrunaAI/pruna)
|
| 16 |
+
[](https://twitter.com/PrunaAI)
|
| 17 |
+
[](https://www.linkedin.com/company/pruna-ai)
|
| 18 |
+
[](https://discord.com/invite/JFQmtFKCjd)
|
| 19 |
+
[](https://dashboard.pruna.ai/login?utm_source=huggingface&utm_medium=org_card&utm_campaign=hf_traffic)
|
| 20 |
+
|
| 21 |
+
<div align="center">
|
| 22 |
+
|
| 23 |
+
<h1 style="color: #9334E9;">⚡ PrunaVAED</h1>
|
| 24 |
+
|
| 25 |
+
<h2>A drop-in replacement decoder for LTX-2.3</h2>
|
| 26 |
+
|
| 27 |
+
<h3>
|
| 28 |
+
<span style="color: #9334E9;">1.7× faster</span>
|
| 29 |
+
·
|
| 30 |
+
<span style="color: #9334E9;">~50% lower peak VRAM</span>
|
| 31 |
+
·
|
| 32 |
+
Near-original visual quality
|
| 33 |
+
</h3>
|
| 34 |
+
|
| 35 |
+
</div>
|
| 36 |
+
|
| 37 |
+
**PrunaVAED directly replaces the video VAE decoder in
|
| 38 |
+
[`diffusers/LTX-2.3-Diffusers`](https://huggingface.co/diffusers/LTX-2.3-Diffusers).
|
| 39 |
+
The encoder and latent format remain unchanged, making it a drop-in upgrade
|
| 40 |
+
for faster, more memory-efficient LTX-2.3 decoding.**
|
| 41 |
+
|
| 42 |
+
## Examples
|
| 43 |
+
|
| 44 |
+
Both columns decode the same LTX-2.3 latent from the distilled pipeline.
|
| 45 |
+
|
| 46 |
+
<table>
|
| 47 |
+
<tr>
|
| 48 |
+
<th align="center">LTX-2.3 decoder</th>
|
| 49 |
+
<th align="center">⚡ PrunaVAED</th>
|
| 50 |
+
</tr>
|
| 51 |
+
<tr>
|
| 52 |
+
<td>
|
| 53 |
+
<video controls autoplay muted loop playsinline
|
| 54 |
+
src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/teacher/04MhZs7YN08-Scene-0048.mp4">
|
| 55 |
+
</video>
|
| 56 |
+
</td>
|
| 57 |
+
<td>
|
| 58 |
+
<video controls autoplay muted loop playsinline
|
| 59 |
+
src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/student/04MhZs7YN08-Scene-0048.mp4">
|
| 60 |
+
</video>
|
| 61 |
+
</td>
|
| 62 |
+
</tr>
|
| 63 |
+
<tr>
|
| 64 |
+
<td>
|
| 65 |
+
<video controls autoplay muted loop playsinline
|
| 66 |
+
src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/teacher/FAfMSWi0FSA-Scene-0200.mp4">
|
| 67 |
+
</video>
|
| 68 |
+
</td>
|
| 69 |
+
<td>
|
| 70 |
+
<video controls autoplay muted loop playsinline
|
| 71 |
+
src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/student/FAfMSWi0FSA-Scene-0200.mp4">
|
| 72 |
+
</video>
|
| 73 |
+
</td>
|
| 74 |
+
</tr>
|
| 75 |
+
</table>
|
| 76 |
+
|
| 77 |
+
<details>
|
| 78 |
+
<summary><strong>More side-by-side comparisons</strong></summary>
|
| 79 |
+
|
| 80 |
+
<br>
|
| 81 |
+
|
| 82 |
+
<table>
|
| 83 |
+
<tr>
|
| 84 |
+
<th align="center">LTX-2.3 decoder</th>
|
| 85 |
+
<th align="center">⚡ PrunaVAED</th>
|
| 86 |
+
</tr>
|
| 87 |
+
<tr>
|
| 88 |
+
<td><video controls autoplay muted loop playsinline src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/teacher/8YSha7iU2ZI-Scene-1025.mp4"></video></td>
|
| 89 |
+
<td><video controls autoplay muted loop playsinline src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/student/8YSha7iU2ZI-Scene-1025.mp4"></video></td>
|
| 90 |
+
</tr>
|
| 91 |
+
<tr>
|
| 92 |
+
<td><video controls autoplay muted loop playsinline src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/teacher/DZt-RtpcJZQ-Scene-0043_teacher.mp4"></video></td>
|
| 93 |
+
<td><video controls autoplay muted loop playsinline src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/student/DZt-RtpcJZQ-Scene-0043_m2.mp4"></video></td>
|
| 94 |
+
</tr>
|
| 95 |
+
<tr>
|
| 96 |
+
<td><video controls autoplay muted loop playsinline src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/teacher/9GDE5-rOOfk-Scene-0010.mp4"></video></td>
|
| 97 |
+
<td><video controls autoplay muted loop playsinline src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/student/9GDE5-rOOfk-Scene-0010.mp4"></video></td>
|
| 98 |
+
</tr>
|
| 99 |
+
<tr>
|
| 100 |
+
<td><video controls autoplay muted loop playsinline src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/teacher/7y57zc-GvBA-Scene-0009.mp4"></video></td>
|
| 101 |
+
<td><video controls autoplay muted loop playsinline src="https://huggingface.co/mehdiPrunaAI/PrunaVAED/resolve/main/example/student/7y57zc-GvBA-Scene-0009.mp4"></video></td>
|
| 102 |
+
</tr>
|
| 103 |
+
</table>
|
| 104 |
+
|
| 105 |
+
</details>
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
## Benchmark
|
| 109 |
+
|
| 110 |
+
Metrics compare videos decoded from the **same latents** by the LTX-2.3 VAED and PrunaVAED. Two set of latents were
|
| 111 |
+
generated with the full
|
| 112 |
+
[`ti2vid_two_stages`](https://github.com/Lightricks/LTX-2/blob/main/packages/ltx-pipelines/src/ltx_pipelines/ti2vid_two_stages.py)
|
| 113 |
+
pipeline and the
|
| 114 |
+
[`distilled`](https://github.com/Lightricks/LTX-2/blob/main/packages/ltx-pipelines/src/ltx_pipelines/distilled.py)
|
| 115 |
+
pipeline (recommended). (~4 s @ 24 fps)
|
| 116 |
+
|
| 117 |
+
| Setting | Value |
|
| 118 |
+
|---|---|
|
| 119 |
+
| Model | PrunaVAED |
|
| 120 |
+
| Precision | `bfloat16` |
|
| 121 |
+
| Batch size | 1 |
|
| 122 |
+
| Device | NVIDIA H100 80GB |
|
| 123 |
+
| Decode | Full (no tiling / rolling / `torch.compile`) |
|
| 124 |
+
|
| 125 |
+
| Latent set | Clips | PSNR ↑ | LPIPS ↓ | SSIM ↑ | Δ-frame PSNR ↑ |
|
| 126 |
+
|---|---:|---:|---:|---:|---:|
|
| 127 |
+
| Distilled two-stage · 720p | 200 | **37.87** | **0.0108** | **0.9898** | **37.28** |
|
| 128 |
+
| TI2Vid two-stage · 720p | 200 | **38.86** | **0.0123** | **0.9803** | **38.98** |
|
| 129 |
+
| Distilled two-stage · 1080p | 200 | **39.59** | **0.0067** | **0.9927** | **39.37** |
|
| 130 |
+
|
| 131 |
+
**Δ-frame PSNR** is PSNR on consecutive-frame
|
| 132 |
+
differences (temporal consistency).
|
| 133 |
+
|
| 134 |
+
## Test
|
| 135 |
+
|
| 136 |
+
End-to-end smoke test: generate a short video with the diffusers LTX-2.3
|
| 137 |
+
**distilled** two-stage pipeline, then decode the same latent with the stock
|
| 138 |
+
LTX-2.3 VAE and with PrunaVAED. Writes two mp4s and prints decode time (ms).
|
| 139 |
+
Needs a **CUDA GPU**.
|
| 140 |
+
|
| 141 |
+
```bash
|
| 142 |
+
# 1. Install the Hugging Face CLI
|
| 143 |
+
pip install hf
|
| 144 |
+
|
| 145 |
+
# 2. Download this repo
|
| 146 |
+
hf download PrunaAI/LTX23-PrunedDecoder --local-dir prunaVAED
|
| 147 |
+
cd prunaVAED
|
| 148 |
+
|
| 149 |
+
# 3. Install dependencies
|
| 150 |
+
pip install -r requirements-test.txt
|
| 151 |
+
|
| 152 |
+
# 4. Run the test (~720p, ~5 s @ 24 fps)
|
| 153 |
+
python tests/test_distilled_decode.py
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
Outputs land in `outputs/test_distilled/` (`ltx23.mp4`, `prunavaed.mp4`).
|
| 157 |
+
Edit `PROMPT` / resolution at the top of `tests/test_distilled_decode.py` if needed.
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
## Architecture
|
| 161 |
+
|
| 162 |
+
PrunaVAED is bitwise identical to LTX 2.3 VAED from `conv_in` to `up_blocks.0`. Pruning starts
|
| 163 |
+
at `up_blocks.1`.
|
| 164 |
+
|
| 165 |
+
| Stage | Channel reduction |
|
| 166 |
+
|---|---:|
|
| 167 |
+
| `up_blocks.0` | unchanged |
|
| 168 |
+
| `up_blocks.1` | 25% |
|
| 169 |
+
| `up_blocks.2` | 50% |
|
| 170 |
+
| `up_blocks.3` | 50% |
|
| 171 |
+
|
| 172 |
+
| | Teacher (LTX-2.3) | PrunaVAED |
|
| 173 |
+
|---|---:|---:|
|
| 174 |
+
| Encoder params | 318.9 M | 318.9 M (unchanged) |
|
| 175 |
+
| Decoder params | 407.2 M | 345.0 M (−15%) |
|
| 176 |
+
| **Total VAE params** | **726.1 M** | **663.9 M** |
|
| 177 |
+
|
| 178 |
+
`prunavaed/patch_diffusers.py` provides the required compatibility shim for
|
| 179 |
+
the pinned diffusers version.
|
| 180 |
+
|
| 181 |
+
## Limitations
|
| 182 |
+
|
| 183 |
+
- Evaluated on 4-second clips at 24 fps.
|
| 184 |
+
- Benchmarked on one H100 80GB with bfloat16 and batch size 1.
|
| 185 |
+
- Speed and VRAM vary with hardware, resolution, batch size, and software.
|
| 186 |
+
- Evaluated only on two differents pipeline of LTX 2.3 ([`ti2vid_two_stages`](https://github.com/Lightricks/LTX-2/blob/main/packages/ltx-pipelines/src/ltx_pipelines/ti2vid_two_stages.py)
|
| 187 |
+
pipeline and the
|
| 188 |
+
[`distilled`](https://github.com/Lightricks/LTX-2/blob/main/packages/ltx-pipelines/src/ltx_pipelines/distilled.py))
|
| 189 |
+
- The weights can be adapted to the custom [`LTX-2`](https://github.com/Lightricks/LTX-2) library without retraining, but no implementation is provided for this yet.
|
| 190 |
+
|
| 191 |
+
## What this is not
|
| 192 |
+
|
| 193 |
+
- Not a full T2V model.
|
| 194 |
+
- Not a replacement for the LTX denoiser/generator.
|
| 195 |
+
- Not compatible with arbitrary VAE latents.
|
| 196 |
+
- Not bit-exact with the original decoder.
|
| 197 |
+
|
| 198 |
+
## License
|
| 199 |
+
|
| 200 |
+
PrunaVAED is a derivative of LTX-2.3 and is distributed under the
|
| 201 |
+
**[LTX-2 Community License Agreement](LICENSE)**. Review its use restrictions
|
| 202 |
+
and commercial terms before using or redistributing the model.
|
| 203 |
+
|
| 204 |
+
Helper code adapted from Hugging Face diffusers retains its Apache-2.0
|
| 205 |
+
attribution; see [`NOTICE`](NOTICE).
|
| 206 |
+
|
| 207 |
+
## Try next
|
| 208 |
+
|
| 209 |
+
- **Use PrunaVAED to speed up LTX-2.3 decoding.**
|
| 210 |
+
- Try Pruna's end-to-end video models:
|
| 211 |
+
[P-Video](https://www.pruna.ai/p-video) and
|
| 212 |
+
[P-Video documentation](https://docs.pruna.ai/en/stable/docs_pruna_endpoints/performance_models/p-video.html).
|
example/student/04MhZs7YN08-Scene-0048.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:43d29de4e52f013f14a82d1f4d41d78f7bb938184f30af48d2e53d09efffe558
|
| 3 |
+
size 1797361
|
example/student/7y57zc-GvBA-Scene-0009.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2de528d80672faf55079399ddf14533ef77b274099407d35fec5fec552b89ae3
|
| 3 |
+
size 1716725
|
example/student/8YSha7iU2ZI-Scene-1025.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c4c8ebfb36da16485337d9b2a48210efa707dedf8992c55be068629e1310c03d
|
| 3 |
+
size 898616
|
example/student/97moBezrzLo-Scene-0076.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c614003deb538d3b02d5e80010f0167b9c1a0fd55e62863479db9ab0e7134c89
|
| 3 |
+
size 1897236
|
example/student/9GDE5-rOOfk-Scene-0010.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:845ad0a7d35633fe3ddf73da94534d468eb2ac36f6faa450db6c841439f785dd
|
| 3 |
+
size 2308198
|
example/student/DZt-RtpcJZQ-Scene-0043_m2.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:06f56792ff2d4793d12b4283c20788e4be6c22ea876729899b7e46614016c1f6
|
| 3 |
+
size 1214808
|
example/student/FAfMSWi0FSA-Scene-0200.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9442659a2cb5b6328bb8f0849b466a4e6b572243f1350efa93cc2cb70261ec10
|
| 3 |
+
size 1883423
|
example/student/a5M8hWgQbjU-Scene-0191.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:af8032ecb4f9e3f5db93ff04293b296979cfba55351f73a1f309e1508d412c83
|
| 3 |
+
size 3051778
|
example/student/ijGuAu0lLNM-Scene-0008.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4eb2af16643f4402da2585878e41257e951141c491556e335b72abab3a9f26eb
|
| 3 |
+
size 1697225
|
example/student/zFehFw9SbDw-Scene-0034.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cf0ff506cb5ade7308c5ad0752bbe57e0b88b37462c5d4f20be10d6c3ff7961b
|
| 3 |
+
size 2129229
|
example/teacher/04MhZs7YN08-Scene-0048.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:320db36560a3b9abac5c710bed668c0b25f8bc3b9cdd1935ba65ecec0ee2174f
|
| 3 |
+
size 1697633
|
example/teacher/7y57zc-GvBA-Scene-0009.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:004434c148e393a6be129a5682fd357b9340f035595d3f09348d764e487dd1e8
|
| 3 |
+
size 1697114
|
example/teacher/8YSha7iU2ZI-Scene-1025.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ddabd909bc729ef15a643a0a63d4937d3846c5165a99d56b83e6e3f06b743179
|
| 3 |
+
size 828088
|
example/teacher/97moBezrzLo-Scene-0076.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:dba2ff092c0d4ed2fe369c9f3525d03f0e6b8d3d240f392a366e89e5b3149ad7
|
| 3 |
+
size 1848784
|
example/teacher/9GDE5-rOOfk-Scene-0010.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a9cb3ab14edb2e0b772b5e472e1d3cb3ef802cba138095d7f52b119ea8a74c44
|
| 3 |
+
size 2239655
|
example/teacher/DZt-RtpcJZQ-Scene-0043_teacher.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:51facb9d24858bd48cdf7e565c4da9c863e875c9121e83b050233c31a59826b6
|
| 3 |
+
size 1174232
|
example/teacher/FAfMSWi0FSA-Scene-0200.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:505d374a8cc0caf0378903199684b2d0db7326ccac7c8f186d9b2eb4690f32ae
|
| 3 |
+
size 1864634
|
example/teacher/a5M8hWgQbjU-Scene-0191.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b7629400d5d318681018cd22bb934d7ba728887c307e8be69853d0d1e01f1526
|
| 3 |
+
size 3360331
|
example/teacher/ijGuAu0lLNM-Scene-0008.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b221c4b8606983128306ed1b6e7d049f300b5439b720a3f5c8bcbc9673f5b8b6
|
| 3 |
+
size 1711726
|
example/teacher/zFehFw9SbDw-Scene-0034.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:688f0d785cb9dafa858a35ac5192380df50483b81392dc1690ad32393ce536d2
|
| 3 |
+
size 2125596
|
patch_diffusers.py
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 Pruna AI
|
| 2 |
+
# Portions adapted from Hugging Face diffusers:
|
| 3 |
+
# Copyright 2026 The HuggingFace Team. Licensed under Apache-2.0.
|
| 4 |
+
|
| 5 |
+
"""Monkey-patch stock diffusers so pruned LTX-2.3 decoder weights load correctly.
|
| 6 |
+
|
| 7 |
+
Stock diffusers builds the decoder graph from ``decoder_block_out_channels`` using
|
| 8 |
+
the *nominal* width of each up block (divided by ``upsample_factor``). It assumes the
|
| 9 |
+
tensor leaving block N always matches that nominal width.
|
| 10 |
+
|
| 11 |
+
PrunaVAED keeps wider skip connections between blocks and only prunes inside each
|
| 12 |
+
block. Example on ``up_blocks.2``:
|
| 13 |
+
|
| 14 |
+
- tensor arriving from ``up_blocks.1``: **384** ch (after 512→384 projection)
|
| 15 |
+
- ResNets inside ``up_blocks.2``: **128** ch (50% pruned vs LTX-2.3 decoder 256)
|
| 16 |
+
- ``conv_in`` projection inside the block: **384 → 256** (feeds the upsampler)
|
| 17 |
+
|
| 18 |
+
Stock diffusers wires ``up_blocks.2`` as 192 → 128 and never creates the 384→256
|
| 19 |
+
``conv_in``, so ``from_pretrained`` fails with shape mismatches on PrunaVAED weights.
|
| 20 |
+
|
| 21 |
+
Fix (two ``__init__`` replacements; forward/decode unchanged)
|
| 22 |
+
------------------------------------------------------------
|
| 23 |
+
1. ``LTX2VideoDecoder3d``: track ``current_channels`` — the actual tensor width
|
| 24 |
+
between blocks — instead of recomputing from the previous block's nominal width.
|
| 25 |
+
2. ``LTX2VideoUpBlock3d``: insert ``conv_in`` when ``in_channels != out_channels *
|
| 26 |
+
upscale_factor`` (pre-upsampler width), not when ``in_channels != out_channels``.
|
| 27 |
+
|
| 28 |
+
The LTX-2.3 decoder is unaffected (no extra projections). Safe to call before any
|
| 29 |
+
``AutoencoderKLLTX2Video.from_pretrained``.
|
| 30 |
+
"""
|
| 31 |
+
|
| 32 |
+
from __future__ import annotations
|
| 33 |
+
|
| 34 |
+
import torch
|
| 35 |
+
import torch.nn as nn
|
| 36 |
+
from diffusers.models.autoencoders import autoencoder_kl_ltx2 as ltx2
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def patch_pruna_ltx2_decoder() -> None:
|
| 40 |
+
if getattr(ltx2, "_PRUNA_LTX2_DECODER_PATCH", False):
|
| 41 |
+
return
|
| 42 |
+
|
| 43 |
+
Resnet = ltx2.LTX2VideoResnetBlock3d
|
| 44 |
+
Upsampler = ltx2.LTX2VideoUpsampler3d
|
| 45 |
+
CausalConv = ltx2.LTX2VideoCausalConv3d
|
| 46 |
+
MidBlock = ltx2.LTX2VideoMidBlock3d
|
| 47 |
+
UpBlock = ltx2.LTX2VideoUpBlock3d
|
| 48 |
+
TimeEmb = ltx2.PixArtAlphaCombinedTimestepSizeEmbeddings
|
| 49 |
+
RMSNorm = ltx2.PerChannelRMSNorm
|
| 50 |
+
|
| 51 |
+
def up_init(
|
| 52 |
+
self,
|
| 53 |
+
in_channels,
|
| 54 |
+
out_channels=None,
|
| 55 |
+
num_layers=1,
|
| 56 |
+
dropout=0.0,
|
| 57 |
+
resnet_eps=1e-6,
|
| 58 |
+
resnet_act_fn="swish",
|
| 59 |
+
spatio_temporal_scale=True,
|
| 60 |
+
upsample_type="spatiotemporal",
|
| 61 |
+
inject_noise=False,
|
| 62 |
+
timestep_conditioning=False,
|
| 63 |
+
upsample_residual=False,
|
| 64 |
+
upscale_factor=1,
|
| 65 |
+
spatial_padding_mode="zeros",
|
| 66 |
+
):
|
| 67 |
+
nn.Module.__init__(self)
|
| 68 |
+
out_channels = out_channels or in_channels
|
| 69 |
+
# Width right before the upsampler (ResNet width × upscale_factor).
|
| 70 |
+
# conv_in projects the incoming skip (e.g. 384) down to this width (e.g. 256).
|
| 71 |
+
pre = out_channels * upscale_factor
|
| 72 |
+
self.time_embedder = TimeEmb(in_channels * 4, 0) if timestep_conditioning else None
|
| 73 |
+
self.conv_in = None
|
| 74 |
+
if in_channels != pre: # stock diffusers compares in_channels != out_channels
|
| 75 |
+
self.conv_in = Resnet(
|
| 76 |
+
in_channels=in_channels,
|
| 77 |
+
out_channels=pre,
|
| 78 |
+
dropout=dropout,
|
| 79 |
+
eps=resnet_eps,
|
| 80 |
+
non_linearity=resnet_act_fn,
|
| 81 |
+
inject_noise=inject_noise,
|
| 82 |
+
timestep_conditioning=timestep_conditioning,
|
| 83 |
+
spatial_padding_mode=spatial_padding_mode,
|
| 84 |
+
)
|
| 85 |
+
self.upsamplers = None
|
| 86 |
+
if spatio_temporal_scale:
|
| 87 |
+
stride = {
|
| 88 |
+
"spatial": (1, 2, 2),
|
| 89 |
+
"temporal": (2, 1, 1),
|
| 90 |
+
"spatiotemporal": (2, 2, 2),
|
| 91 |
+
}[upsample_type]
|
| 92 |
+
self.upsamplers = nn.ModuleList(
|
| 93 |
+
[
|
| 94 |
+
Upsampler(
|
| 95 |
+
in_channels=pre,
|
| 96 |
+
stride=stride,
|
| 97 |
+
residual=upsample_residual,
|
| 98 |
+
upscale_factor=upscale_factor,
|
| 99 |
+
spatial_padding_mode=spatial_padding_mode,
|
| 100 |
+
),
|
| 101 |
+
]
|
| 102 |
+
)
|
| 103 |
+
self.resnets = nn.ModuleList(
|
| 104 |
+
[
|
| 105 |
+
Resnet(
|
| 106 |
+
in_channels=out_channels,
|
| 107 |
+
out_channels=out_channels,
|
| 108 |
+
dropout=dropout,
|
| 109 |
+
eps=resnet_eps,
|
| 110 |
+
non_linearity=resnet_act_fn,
|
| 111 |
+
inject_noise=inject_noise,
|
| 112 |
+
timestep_conditioning=timestep_conditioning,
|
| 113 |
+
spatial_padding_mode=spatial_padding_mode,
|
| 114 |
+
)
|
| 115 |
+
for _ in range(num_layers)
|
| 116 |
+
]
|
| 117 |
+
)
|
| 118 |
+
self.gradient_checkpointing = False
|
| 119 |
+
|
| 120 |
+
def decoder_init(
|
| 121 |
+
self,
|
| 122 |
+
in_channels=128,
|
| 123 |
+
out_channels=3,
|
| 124 |
+
block_out_channels=(256, 512, 1024),
|
| 125 |
+
spatio_temporal_scaling=(True, True, True),
|
| 126 |
+
layers_per_block=(5, 5, 5, 5),
|
| 127 |
+
upsample_type=("spatiotemporal", "spatiotemporal", "spatiotemporal"),
|
| 128 |
+
patch_size=4,
|
| 129 |
+
patch_size_t=1,
|
| 130 |
+
resnet_norm_eps=1e-6,
|
| 131 |
+
is_causal=False,
|
| 132 |
+
inject_noise=(False, False, False),
|
| 133 |
+
timestep_conditioning=False,
|
| 134 |
+
upsample_residual=(True, True, True),
|
| 135 |
+
upsample_factor=(2, 2, 2),
|
| 136 |
+
spatial_padding_mode="reflect",
|
| 137 |
+
):
|
| 138 |
+
nn.Module.__init__(self)
|
| 139 |
+
n = len(layers_per_block)
|
| 140 |
+
if isinstance(spatio_temporal_scaling, bool):
|
| 141 |
+
spatio_temporal_scaling = (spatio_temporal_scaling,) * (n - 1)
|
| 142 |
+
if isinstance(inject_noise, bool):
|
| 143 |
+
inject_noise = (inject_noise,) * n
|
| 144 |
+
if isinstance(upsample_residual, bool):
|
| 145 |
+
upsample_residual = (upsample_residual,) * (n - 1)
|
| 146 |
+
|
| 147 |
+
self.patch_size, self.patch_size_t = patch_size, patch_size_t
|
| 148 |
+
self.out_channels = out_channels * patch_size**2
|
| 149 |
+
self.is_causal = is_causal
|
| 150 |
+
|
| 151 |
+
ch = tuple(reversed(block_out_channels))
|
| 152 |
+
spatio_temporal_scaling = tuple(reversed(spatio_temporal_scaling))
|
| 153 |
+
layers_per_block = tuple(reversed(layers_per_block))
|
| 154 |
+
inject_noise = tuple(reversed(inject_noise))
|
| 155 |
+
upsample_residual = tuple(reversed(upsample_residual))
|
| 156 |
+
upsample_factor = tuple(reversed(upsample_factor))
|
| 157 |
+
upsample_type = tuple(upsample_type)
|
| 158 |
+
if len(upsample_type) == len(ch) - 1:
|
| 159 |
+
upsample_type = tuple(reversed(upsample_type))
|
| 160 |
+
|
| 161 |
+
width = ch[0]
|
| 162 |
+
self.conv_in = CausalConv(
|
| 163 |
+
in_channels=in_channels,
|
| 164 |
+
out_channels=width,
|
| 165 |
+
kernel_size=3,
|
| 166 |
+
stride=1,
|
| 167 |
+
spatial_padding_mode=spatial_padding_mode,
|
| 168 |
+
)
|
| 169 |
+
self.mid_block = MidBlock(
|
| 170 |
+
in_channels=width,
|
| 171 |
+
num_layers=layers_per_block[0],
|
| 172 |
+
resnet_eps=resnet_norm_eps,
|
| 173 |
+
inject_noise=inject_noise[0],
|
| 174 |
+
timestep_conditioning=timestep_conditioning,
|
| 175 |
+
spatial_padding_mode=spatial_padding_mode,
|
| 176 |
+
)
|
| 177 |
+
|
| 178 |
+
# Stock: input_channel = previous_nominal // factor (loses pruned skip widths).
|
| 179 |
+
# Patched: pass the real tensor width from the previous block as in_channels.
|
| 180 |
+
self.up_blocks = nn.ModuleList()
|
| 181 |
+
current = width
|
| 182 |
+
for i in range(len(ch)):
|
| 183 |
+
resnet_w = ch[i] // upsample_factor[i]
|
| 184 |
+
self.up_blocks.append(
|
| 185 |
+
UpBlock(
|
| 186 |
+
in_channels=current,
|
| 187 |
+
out_channels=resnet_w,
|
| 188 |
+
num_layers=layers_per_block[i + 1],
|
| 189 |
+
resnet_eps=resnet_norm_eps,
|
| 190 |
+
spatio_temporal_scale=spatio_temporal_scaling[i],
|
| 191 |
+
upsample_type=upsample_type[i],
|
| 192 |
+
inject_noise=inject_noise[i + 1],
|
| 193 |
+
timestep_conditioning=timestep_conditioning,
|
| 194 |
+
upsample_residual=upsample_residual[i],
|
| 195 |
+
upscale_factor=upsample_factor[i],
|
| 196 |
+
spatial_padding_mode=spatial_padding_mode,
|
| 197 |
+
)
|
| 198 |
+
)
|
| 199 |
+
current = resnet_w
|
| 200 |
+
|
| 201 |
+
self.norm_out = RMSNorm()
|
| 202 |
+
self.conv_act = nn.SiLU()
|
| 203 |
+
self.conv_out = CausalConv(
|
| 204 |
+
in_channels=current,
|
| 205 |
+
out_channels=self.out_channels,
|
| 206 |
+
kernel_size=3,
|
| 207 |
+
stride=1,
|
| 208 |
+
spatial_padding_mode=spatial_padding_mode,
|
| 209 |
+
)
|
| 210 |
+
self.time_embedder = self.scale_shift_table = self.timestep_scale_multiplier = None
|
| 211 |
+
if timestep_conditioning:
|
| 212 |
+
self.timestep_scale_multiplier = nn.Parameter(torch.tensor(1000.0))
|
| 213 |
+
self.time_embedder = TimeEmb(width * 2, 0)
|
| 214 |
+
self.scale_shift_table = nn.Parameter(torch.randn(2, width) / width**0.5)
|
| 215 |
+
self.gradient_checkpointing = False
|
| 216 |
+
|
| 217 |
+
UpBlock.__init__ = up_init
|
| 218 |
+
ltx2.LTX2VideoDecoder3d.__init__ = decoder_init
|
| 219 |
+
ltx2._PRUNA_LTX2_DECODER_PATCH = True
|
requirements-test.txt
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
--extra-index-url https://download.pytorch.org/whl/cu130
|
| 2 |
+
torch==2.11.0+cu130
|
| 3 |
+
torchvision==0.26.0+cu130
|
| 4 |
+
torchaudio==2.11.0+cu130
|
| 5 |
+
diffusers==0.39.0
|
| 6 |
+
huggingface_hub==1.24.0
|
| 7 |
+
safetensors==0.8.0
|
| 8 |
+
accelerate==1.13.0
|
| 9 |
+
imageio==2.37.3
|
| 10 |
+
imageio-ffmpeg==0.6.0
|
| 11 |
+
|
| 12 |
+
transformers>=4.57.0
|
| 13 |
+
sentencepiece>=0.2.0
|
| 14 |
+
protobuf>=5.0.0
|
| 15 |
+
Pillow>=10.0.0
|
| 16 |
+
numpy>=1.24.0
|
| 17 |
+
tqdm>=4.66.0
|
| 18 |
+
av>=14.0.0
|
| 19 |
+
pytest>=8.0.0
|
tests/test_distilled_decode.py
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Quick demo: generate a short LTX-2.3 video latent, then decode it twice.
|
| 3 |
+
|
| 4 |
+
Compares the stock LTX-2.3 VAE decoder with this repo's pruned decoder
|
| 5 |
+
(PrunaVAED) on the *same* latent. Prints decode time (ms) and writes two mp4s.
|
| 6 |
+
|
| 7 |
+
Requires a CUDA GPU. From the repo root:
|
| 8 |
+
|
| 9 |
+
pip install -r requirements-test.txt
|
| 10 |
+
python tests/test_distilled_decode.py
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
from __future__ import annotations
|
| 14 |
+
|
| 15 |
+
import statistics
|
| 16 |
+
import sys
|
| 17 |
+
import time
|
| 18 |
+
from pathlib import Path
|
| 19 |
+
|
| 20 |
+
import imageio.v3 as iio
|
| 21 |
+
import torch
|
| 22 |
+
from diffusers import LTX2LatentUpsamplePipeline, LTX2Pipeline
|
| 23 |
+
from diffusers.models.autoencoders import AutoencoderKLLTX2Video
|
| 24 |
+
from diffusers.pipelines.ltx2.latent_upsampler import LTX2LatentUpsamplerModel
|
| 25 |
+
from diffusers.pipelines.ltx2.utils import (
|
| 26 |
+
DEFAULT_NEGATIVE_PROMPT,
|
| 27 |
+
DISTILLED_SIGMA_VALUES,
|
| 28 |
+
STAGE_2_DISTILLED_SIGMA_VALUES,
|
| 29 |
+
)
|
| 30 |
+
|
| 31 |
+
torch.backends.cuda.enable_cudnn_sdp(False)
|
| 32 |
+
|
| 33 |
+
# ---------------------------------------------------------------------------
|
| 34 |
+
# Settings (edit these if you want)
|
| 35 |
+
# ---------------------------------------------------------------------------
|
| 36 |
+
|
| 37 |
+
REPO_ROOT = Path(__file__).resolve().parents[1]
|
| 38 |
+
sys.path.insert(0, str(REPO_ROOT))
|
| 39 |
+
|
| 40 |
+
from patch_diffusers import patch_pruna_ltx2_decoder # noqa: E402
|
| 41 |
+
|
| 42 |
+
# Official Diffusers checkpoints for the 2-stage distilled recipe.
|
| 43 |
+
DISTILLED_MODEL = "diffusers/LTX-2.3-Distilled-Diffusers"
|
| 44 |
+
SPATIAL_UPSAMPLER = "dg845/LTX-2.3-Spatial-Upsampler-Diffusers"
|
| 45 |
+
LTX23_VAE = "diffusers/LTX-2.3-Diffusers" # stock decoder (baseline)
|
| 46 |
+
PRUNED_VAE = REPO_ROOT # this repo's vae/ folder
|
| 47 |
+
|
| 48 |
+
# ~720p for 5 s @ 24 fps. Height/width must be multiples of 64 (2-stage).
|
| 49 |
+
HEIGHT, WIDTH, NUM_FRAMES, FPS = 704, 1280, 121, 24.0
|
| 50 |
+
SEED = 42
|
| 51 |
+
DECODE_WARMUP, DECODE_RUNS = 1, 3 # timing: 1 warm-up + median of 3 runs
|
| 52 |
+
|
| 53 |
+
PROMPT = (
|
| 54 |
+
"In the video, a man is seen riding a skateboard in an indoor skate park. "
|
| 55 |
+
"He is wearing a black cap, a grey t-shirt, and black pants. The skate park "
|
| 56 |
+
"has a wooden floor and a ramp. The man performs a trick by jumping and "
|
| 57 |
+
"flipping the skateboard under his feet while in the air. He lands on the "
|
| 58 |
+
"skateboard and continues to ride it."
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
DEVICE = "cuda"
|
| 62 |
+
DTYPE = torch.bfloat16
|
| 63 |
+
OUTPUT_DIR = REPO_ROOT / "outputs" / "test_distilled"
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
# ---------------------------------------------------------------------------
|
| 67 |
+
# Helpers
|
| 68 |
+
# ---------------------------------------------------------------------------
|
| 69 |
+
|
| 70 |
+
def save_mp4(video: torch.Tensor, path: Path) -> None:
|
| 71 |
+
"""Save a BCTHW tensor in [-1, 1] as an H.264 mp4."""
|
| 72 |
+
frames = video[0].permute(1, 2, 3, 0).clamp(-1, 1)
|
| 73 |
+
frames = ((frames + 1) / 2 * 255).byte().cpu().numpy()
|
| 74 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 75 |
+
iio.imwrite(path, frames, fps=FPS, codec="libx264")
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def load_vae(model_id: str) -> AutoencoderKLLTX2Video:
|
| 79 |
+
"""Load a video VAE decoder and put it on GPU."""
|
| 80 |
+
vae = AutoencoderKLLTX2Video.from_pretrained(
|
| 81 |
+
model_id, subfolder="vae", torch_dtype=DTYPE
|
| 82 |
+
)
|
| 83 |
+
vae = vae.to(DEVICE).eval()
|
| 84 |
+
vae.use_tiling = False
|
| 85 |
+
if hasattr(vae, "disable_tiling"):
|
| 86 |
+
vae.disable_tiling()
|
| 87 |
+
return vae
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
@torch.inference_mode()
|
| 91 |
+
def timed_decode(vae: AutoencoderKLLTX2Video, latent: torch.Tensor) -> tuple[torch.Tensor, float]:
|
| 92 |
+
"""Decode once after warm-up; return (video on CPU, median latency in ms)."""
|
| 93 |
+
latent = latent.to(DEVICE, DTYPE)
|
| 94 |
+
|
| 95 |
+
with torch.autocast(DEVICE, dtype=DTYPE):
|
| 96 |
+
for _ in range(DECODE_WARMUP):
|
| 97 |
+
vae.decode(latent, return_dict=False)
|
| 98 |
+
|
| 99 |
+
times_ms = []
|
| 100 |
+
video = None
|
| 101 |
+
for _ in range(DECODE_RUNS):
|
| 102 |
+
torch.cuda.synchronize()
|
| 103 |
+
t0 = time.perf_counter()
|
| 104 |
+
with torch.autocast(DEVICE, dtype=DTYPE):
|
| 105 |
+
video = vae.decode(latent, return_dict=False)[0]
|
| 106 |
+
torch.cuda.synchronize()
|
| 107 |
+
times_ms.append((time.perf_counter() - t0) * 1000)
|
| 108 |
+
|
| 109 |
+
return video.cpu(), statistics.median(times_ms)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
@torch.inference_mode()
|
| 113 |
+
def generate_latent(prompt: str) -> torch.Tensor:
|
| 114 |
+
"""Run the official 2-stage distilled pipeline and return the final video latent.
|
| 115 |
+
|
| 116 |
+
Same layout as Lightricks DistilledPipeline:
|
| 117 |
+
stage 1 @ half-res → 2× latent upsample → stage 2 @ full-res.
|
| 118 |
+
"""
|
| 119 |
+
half_h, half_w = HEIGHT // 2, WIDTH // 2
|
| 120 |
+
generator = torch.Generator(DEVICE).manual_seed(SEED)
|
| 121 |
+
|
| 122 |
+
pipe = LTX2Pipeline.from_pretrained(DISTILLED_MODEL, torch_dtype=DTYPE)
|
| 123 |
+
pipe.enable_model_cpu_offload(device=DEVICE)
|
| 124 |
+
|
| 125 |
+
# Stage 1 — cheap draft at half resolution.
|
| 126 |
+
print(f"1/3 Stage 1 @ {half_w}×{half_h}")
|
| 127 |
+
video_latent, audio_latent = pipe(
|
| 128 |
+
prompt=prompt,
|
| 129 |
+
negative_prompt=DEFAULT_NEGATIVE_PROMPT,
|
| 130 |
+
height=half_h,
|
| 131 |
+
width=half_w,
|
| 132 |
+
num_frames=NUM_FRAMES,
|
| 133 |
+
frame_rate=FPS,
|
| 134 |
+
num_inference_steps=len(DISTILLED_SIGMA_VALUES),
|
| 135 |
+
sigmas=DISTILLED_SIGMA_VALUES,
|
| 136 |
+
guidance_scale=1.0,
|
| 137 |
+
generator=generator,
|
| 138 |
+
output_type="latent",
|
| 139 |
+
return_dict=False,
|
| 140 |
+
)
|
| 141 |
+
|
| 142 |
+
# Upsample — bring the latent to full resolution before refining.
|
| 143 |
+
print(f"2/3 Upsample → {WIDTH}×{HEIGHT}")
|
| 144 |
+
upsampler = LTX2LatentUpsamplerModel.from_pretrained(
|
| 145 |
+
SPATIAL_UPSAMPLER, subfolder="latent_upsampler", torch_dtype=DTYPE
|
| 146 |
+
)
|
| 147 |
+
upsample_pipe = LTX2LatentUpsamplePipeline(vae=pipe.vae, latent_upsampler=upsampler)
|
| 148 |
+
upsample_pipe.enable_model_cpu_offload(device=DEVICE)
|
| 149 |
+
video_latent = upsample_pipe(
|
| 150 |
+
latents=video_latent[:1],
|
| 151 |
+
height=half_h,
|
| 152 |
+
width=half_w,
|
| 153 |
+
num_frames=NUM_FRAMES,
|
| 154 |
+
output_type="latent",
|
| 155 |
+
return_dict=False,
|
| 156 |
+
)[0]
|
| 157 |
+
del upsample_pipe, upsampler
|
| 158 |
+
torch.cuda.empty_cache()
|
| 159 |
+
|
| 160 |
+
# Stage 2 — refine at full resolution (renoises from STAGE_2 schedule).
|
| 161 |
+
print(f"3/3 Stage 2 @ {WIDTH}×{HEIGHT}")
|
| 162 |
+
video_latent, _ = pipe(
|
| 163 |
+
latents=video_latent,
|
| 164 |
+
audio_latents=audio_latent,
|
| 165 |
+
prompt=prompt,
|
| 166 |
+
negative_prompt=DEFAULT_NEGATIVE_PROMPT,
|
| 167 |
+
height=HEIGHT,
|
| 168 |
+
width=WIDTH,
|
| 169 |
+
num_frames=NUM_FRAMES,
|
| 170 |
+
frame_rate=FPS,
|
| 171 |
+
num_inference_steps=len(STAGE_2_DISTILLED_SIGMA_VALUES),
|
| 172 |
+
noise_scale=STAGE_2_DISTILLED_SIGMA_VALUES[0],
|
| 173 |
+
sigmas=STAGE_2_DISTILLED_SIGMA_VALUES,
|
| 174 |
+
guidance_scale=1.0,
|
| 175 |
+
generator=generator,
|
| 176 |
+
output_type="latent",
|
| 177 |
+
return_dict=False,
|
| 178 |
+
)
|
| 179 |
+
|
| 180 |
+
latent = video_latent.detach().cpu()
|
| 181 |
+
del pipe
|
| 182 |
+
torch.cuda.empty_cache()
|
| 183 |
+
return latent
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
def compare_decoders(latent: torch.Tensor, out_dir: Path) -> None:
|
| 187 |
+
"""Decode the same latent with LTX-2.3 and PrunaVAED; print ms and save mp4s."""
|
| 188 |
+
# Needed so Diffusers can build the pruned decoder graph correctly.
|
| 189 |
+
patch_pruna_ltx2_decoder()
|
| 190 |
+
|
| 191 |
+
results = {}
|
| 192 |
+
for name, model_id in (("ltx23", LTX23_VAE), ("prunavaed", str(PRUNED_VAE))):
|
| 193 |
+
print(f"Decoding with {name} …")
|
| 194 |
+
vae = load_vae(model_id)
|
| 195 |
+
video, ms = timed_decode(vae, latent)
|
| 196 |
+
results[name] = ms
|
| 197 |
+
path = out_dir / f"{name}.mp4"
|
| 198 |
+
save_mp4(video, path)
|
| 199 |
+
print(f" {name}: {ms:.1f} ms → {path}")
|
| 200 |
+
del vae, video
|
| 201 |
+
torch.cuda.empty_cache()
|
| 202 |
+
|
| 203 |
+
print(f"Speedup: {results['ltx23'] / results['prunavaed']:.2f}×")
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
# ---------------------------------------------------------------------------
|
| 207 |
+
# Entry point
|
| 208 |
+
# ---------------------------------------------------------------------------
|
| 209 |
+
|
| 210 |
+
def main() -> None:
|
| 211 |
+
if not torch.cuda.is_available():
|
| 212 |
+
raise SystemExit("This demo needs a CUDA GPU.")
|
| 213 |
+
|
| 214 |
+
print(f"Prompt: {PROMPT[:80]}…")
|
| 215 |
+
print(f"Output: {OUTPUT_DIR}")
|
| 216 |
+
|
| 217 |
+
latent = generate_latent(PROMPT)
|
| 218 |
+
print(f"Latent shape: {tuple(latent.shape)}")
|
| 219 |
+
compare_decoders(latent, OUTPUT_DIR)
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
if __name__ == "__main__":
|
| 223 |
+
main()
|
vae/config.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_class_name": "AutoencoderKLLTX2Video",
|
| 3 |
+
"_diffusers_version": "0.38.0",
|
| 4 |
+
"aligned_blks_indices": null,
|
| 5 |
+
"aligned_feature_projection_dim": null,
|
| 6 |
+
"aligned_feature_projection_mode": null,
|
| 7 |
+
"block_out_channels": [
|
| 8 |
+
256,
|
| 9 |
+
512,
|
| 10 |
+
1024,
|
| 11 |
+
1024
|
| 12 |
+
],
|
| 13 |
+
"decoder_block_out_channels": [
|
| 14 |
+
128,
|
| 15 |
+
256,
|
| 16 |
+
384,
|
| 17 |
+
1024
|
| 18 |
+
],
|
| 19 |
+
"decoder_causal": false,
|
| 20 |
+
"decoder_inject_noise": [
|
| 21 |
+
false,
|
| 22 |
+
false,
|
| 23 |
+
false,
|
| 24 |
+
false,
|
| 25 |
+
false
|
| 26 |
+
],
|
| 27 |
+
"decoder_layers_per_block": [
|
| 28 |
+
4,
|
| 29 |
+
6,
|
| 30 |
+
4,
|
| 31 |
+
2,
|
| 32 |
+
2
|
| 33 |
+
],
|
| 34 |
+
"decoder_spatial_padding_mode": "zeros",
|
| 35 |
+
"decoder_spatio_temporal_scaling": [
|
| 36 |
+
true,
|
| 37 |
+
true,
|
| 38 |
+
true,
|
| 39 |
+
true
|
| 40 |
+
],
|
| 41 |
+
"down_block_types": [
|
| 42 |
+
"LTX2VideoDownBlock3D",
|
| 43 |
+
"LTX2VideoDownBlock3D",
|
| 44 |
+
"LTX2VideoDownBlock3D",
|
| 45 |
+
"LTX2VideoDownBlock3D"
|
| 46 |
+
],
|
| 47 |
+
"downsample_type": [
|
| 48 |
+
"spatial",
|
| 49 |
+
"temporal",
|
| 50 |
+
"spatiotemporal",
|
| 51 |
+
"spatiotemporal"
|
| 52 |
+
],
|
| 53 |
+
"encoder_causal": true,
|
| 54 |
+
"encoder_spatial_padding_mode": "zeros",
|
| 55 |
+
"in_channels": 3,
|
| 56 |
+
"latent_channels": 128,
|
| 57 |
+
"layers_per_block": [
|
| 58 |
+
4,
|
| 59 |
+
6,
|
| 60 |
+
4,
|
| 61 |
+
2,
|
| 62 |
+
2
|
| 63 |
+
],
|
| 64 |
+
"out_channels": 3,
|
| 65 |
+
"patch_size": 4,
|
| 66 |
+
"patch_size_t": 1,
|
| 67 |
+
"resnet_norm_eps": 1e-06,
|
| 68 |
+
"scaling_factor": 1.0,
|
| 69 |
+
"spatial_compression_ratio": 32,
|
| 70 |
+
"spatio_temporal_scaling": [
|
| 71 |
+
true,
|
| 72 |
+
true,
|
| 73 |
+
true,
|
| 74 |
+
true
|
| 75 |
+
],
|
| 76 |
+
"temporal_compression_ratio": 8,
|
| 77 |
+
"timestep_conditioning": false,
|
| 78 |
+
"upsample_factor": [
|
| 79 |
+
2,
|
| 80 |
+
2,
|
| 81 |
+
1,
|
| 82 |
+
2
|
| 83 |
+
],
|
| 84 |
+
"upsample_residual": [
|
| 85 |
+
false,
|
| 86 |
+
false,
|
| 87 |
+
false,
|
| 88 |
+
false
|
| 89 |
+
],
|
| 90 |
+
"upsample_type": [
|
| 91 |
+
"spatiotemporal",
|
| 92 |
+
"spatiotemporal",
|
| 93 |
+
"temporal",
|
| 94 |
+
"spatial"
|
| 95 |
+
]
|
| 96 |
+
}
|
vae/diffusion_pytorch_model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d2fe12c4f25ac2fbfec6e5f3e9d481f70caf52be24471f114f7d09f26f8340dd
|
| 3 |
+
size 1327909418
|