daKhosa commited on
Commit
ab07e2b
·
1 Parent(s): 4bd6143

Untrack 10Eros subfolder; ignore it from Sulphur repo

Browse files
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ 10Eros/
10Eros/.gitattributes DELETED
@@ -1,35 +0,0 @@
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10Eros/README.md DELETED
@@ -1,24 +0,0 @@
1
- ---
2
- title: LTX2.3-10Eros
3
- emoji: 🔥
4
- colorFrom: orange
5
- colorTo: red
6
- sdk: gradio
7
- sdk_version: "6.14.0"
8
- python_version: "3.12"
9
- app_file: app.py
10
- pinned: false
11
- license: mit
12
- ---
13
-
14
- # 10Eros — Image to Video
15
-
16
- Upload an image and prompt, and 10Eros will animate it into a short video clip.
17
-
18
- **Model**
19
- - **10Eros** — LTX-2.3 layer-scaled merge built on Sulphur-2-base
20
-
21
- **Tips**
22
- - Landscape images work best at 832×480; portrait at 480×832
23
- - Keep prompts focused on motion (e.g. "hair blowing in the wind, slow pan")
24
- - 8 steps is fast; raise to 20–30 for finer detail
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10Eros/app.py DELETED
@@ -1,203 +0,0 @@
1
- """
2
- 10Eros — Image to Video (HF Spaces).
3
- Clones Wan2GP and downloads models on first run.
4
- Generation is handled by generate.py called as a subprocess inside @spaces.GPU.
5
- """
6
-
7
- import os
8
- import sys
9
- import subprocess
10
- import shutil
11
- import tempfile
12
- import threading
13
- import json
14
- from pathlib import Path
15
-
16
- import gradio as gr
17
- import spaces
18
-
19
- _HF_TOKEN = os.environ.get("HF_TOKEN")
20
- _PERSISTENT = Path("/data") if Path("/data").exists() else Path(tempfile.gettempdir())
21
- WAN2GP_ROOT = _PERSISTENT / "Wan2GP"
22
- CKPTS_DIR = WAN2GP_ROOT / "ckpts"
23
- LORAS_DIR = WAN2GP_ROOT / "loras" / "ltx2"
24
- FINETUNES_DIR = WAN2GP_ROOT / "finetunes"
25
- GENERATE_PY = Path(__file__).parent / "generate.py"
26
-
27
- MODEL_ASSETS = [
28
- ("TenStrip/LTX2.3-10Eros", "10Eros_v1_bf16.safetensors", CKPTS_DIR),
29
- ]
30
- LTX_ASSETS = [
31
- ("SulphurAI/Sulphur-2-base", "distill_loras/ltx-2.3-22b-distilled-lora-1.1_fro90_ceil72_condsafe.safetensors", LORAS_DIR),
32
- ("DeepBeepMeep/LTX-2", "ltx-2.3-22b_vae.safetensors", CKPTS_DIR),
33
- ("DeepBeepMeep/LTX-2", "ltx-2.3-22b_text_embedding_projection.safetensors", CKPTS_DIR),
34
- ("DeepBeepMeep/LTX-2", "ltx-2.3-22b_embeddings_connector.safetensors", CKPTS_DIR),
35
- ]
36
-
37
- MODEL_FINETUNE = {
38
- "model": {
39
- "name": "10Eros",
40
- "visible": True,
41
- "architecture": "ltx2_22B",
42
- "parent_model_type": "ltx2_22B",
43
- "description": "LTX-2.3 layer-scaled merge i2v. Built on Sulphur-2-base.",
44
- "URLs": [str(CKPTS_DIR / "10Eros_v1_bf16.safetensors")],
45
- "preload_URLs": [],
46
- },
47
- "num_inference_steps": 8,
48
- "video_length": 81,
49
- "resolution": "832x480",
50
- "guidance_scale": 3.5,
51
- "alt_guidance_scale": 3.5,
52
- }
53
-
54
- _setup_lock = threading.Lock()
55
- _setup_done = False
56
-
57
-
58
- def _download(repo_id, filename, dest_dir):
59
- from huggingface_hub import hf_hub_download
60
- dest_dir.mkdir(parents=True, exist_ok=True)
61
- dest = dest_dir / Path(filename).name # flat — strip any subfolder
62
- if dest.exists():
63
- print(f"[download] cached: {dest.name}")
64
- return
65
- print(f"[download] {repo_id}/{filename}")
66
- hf_hub_download(repo_id=repo_id, filename=filename,
67
- local_dir=str(dest_dir), token=_HF_TOKEN)
68
- # hf_hub_download preserves subfolder structure; flatten to dest_dir root
69
- downloaded = dest_dir / filename
70
- if downloaded.exists() and not dest.exists():
71
- shutil.move(str(downloaded), str(dest))
72
-
73
-
74
- def setup():
75
- global _setup_done
76
- with _setup_lock:
77
- if _setup_done:
78
- return
79
- _setup_done = True
80
-
81
- if not (WAN2GP_ROOT / "shared" / "api.py").exists():
82
- WAN2GP_ROOT.mkdir(parents=True, exist_ok=True)
83
- print("[setup] Cloning Wan2GP...")
84
- subprocess.run(
85
- ["git", "clone", "--depth=1",
86
- "https://github.com/deepbeepmeep/Wan2GP.git", str(WAN2GP_ROOT)],
87
- check=True,
88
- )
89
-
90
- for repo, fname, dest in MODEL_ASSETS + LTX_ASSETS:
91
- _download(repo, fname, dest)
92
-
93
- # Gemma text encoder — must stay in its subfolder (Wan2GP looks there by name)
94
- _gemma_folder = "gemma-3-12b-it-qat-q4_0-unquantized"
95
- _gemma_file = f"{_gemma_folder}_quanto_bf16_int8.safetensors"
96
- gemma_dest = CKPTS_DIR / _gemma_folder / _gemma_file
97
- if not gemma_dest.exists():
98
- from huggingface_hub import hf_hub_download
99
- print("[download] Gemma text encoder...")
100
- hf_hub_download(
101
- repo_id="DeepBeepMeep/LTX-2",
102
- filename=f"{_gemma_folder}/{_gemma_file}",
103
- local_dir=str(CKPTS_DIR),
104
- token=_HF_TOKEN,
105
- )
106
- else:
107
- print("[download] cached: Gemma text encoder")
108
-
109
- FINETUNES_DIR.mkdir(parents=True, exist_ok=True)
110
- (FINETUNES_DIR / "ten_eros.json").write_text(json.dumps(MODEL_FINETUNE, indent=2))
111
- print("[setup] Done.")
112
-
113
-
114
- setup()
115
-
116
- RESOLUTIONS = ["832x480", "480x832", "640x640", "1024x576", "576x1024"]
117
-
118
-
119
- @spaces.GPU(duration=120)
120
- def generate_video(image, prompt, resolution, steps, guidance_scale, frames, seed):
121
- if image is None:
122
- raise gr.Error("Please upload an image.")
123
- if not prompt.strip():
124
- raise gr.Error("Please enter a prompt.")
125
-
126
- out_file = Path(tempfile.mkdtemp()) / "output.mp4"
127
- env = {**os.environ, "WAN2GP_ROOT": str(WAN2GP_ROOT)}
128
-
129
- cmd = [
130
- sys.executable, str(GENERATE_PY),
131
- "--image", image,
132
- "--prompt", prompt,
133
- "--output", str(out_file),
134
- "--model", "10eros",
135
- "--seed", str(int(seed)),
136
- "--resolution", resolution,
137
- "--steps", str(int(steps)),
138
- "--guidance_scale", str(float(guidance_scale)),
139
- "--frames", str(int(frames)),
140
- ]
141
-
142
- log_lines = []
143
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
144
- text=True, bufsize=0, env=env)
145
-
146
- buf = ""
147
- while True:
148
- chunk = proc.stdout.read(256)
149
- if not chunk:
150
- break
151
- buf += chunk
152
- # Split on \r or \n — tqdm uses \r to overwrite progress lines
153
- parts = buf.replace("\r", "\n").split("\n")
154
- buf = parts[-1]
155
- for part in parts[:-1]:
156
- stripped = part.strip()
157
- if not stripped:
158
- continue
159
- # Overwrite last line if it looks like a progress bar update
160
- if log_lines and ("%" in stripped or "it/s" in stripped or "step" in stripped.lower()):
161
- log_lines[-1] = stripped
162
- else:
163
- log_lines.append(stripped)
164
- print(stripped)
165
- yield None, "\n".join(log_lines[-30:])
166
-
167
- proc.wait()
168
- log = "\n".join(log_lines)
169
-
170
- if proc.returncode != 0 or not out_file.exists():
171
- yield None, log + "\n\n[ERROR] Generation failed."
172
- return
173
-
174
- final = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
175
- shutil.copy2(out_file, final.name)
176
- yield final.name, log + "\n\n[DONE]"
177
-
178
-
179
- with gr.Blocks(title="10Eros — Image to Video") as demo:
180
- gr.Markdown("# 10Eros — Image to Video\nPowered by Wan2GP · LTX-2.3 layer-scaled merge")
181
- with gr.Row():
182
- with gr.Column(scale=1):
183
- image_in = gr.Image(type="filepath", label="Input Image")
184
- prompt_in = gr.Textbox(label="Prompt", placeholder="Describe the motion…", lines=3)
185
- with gr.Accordion("Advanced", open=False):
186
- resolution_dd = gr.Dropdown(RESOLUTIONS, value="832x480", label="Resolution")
187
- steps_sl = gr.Slider(1, 50, value=8, step=1, label="Steps")
188
- guidance_sl = gr.Slider(1.0, 10.0, value=5.0, step=0.5, label="Guidance Scale")
189
- frames_sl = gr.Slider(17, 257, value=81, step=8, label="Frames")
190
- seed_num = gr.Number(value=-1, label="Seed (-1 = random)", precision=0)
191
- run_btn = gr.Button("Generate", variant="primary")
192
- with gr.Column(scale=1):
193
- video_out = gr.Video(label="Output Video")
194
- log_out = gr.Textbox(label="Log", lines=10, interactive=False)
195
-
196
- run_btn.click(
197
- fn=generate_video,
198
- inputs=[image_in, prompt_in, resolution_dd, steps_sl, guidance_sl, frames_sl, seed_num],
199
- outputs=[video_out, log_out],
200
- )
201
-
202
- if __name__ == "__main__":
203
- demo.launch(theme=gr.themes.Soft())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10Eros/generate.py DELETED
@@ -1,139 +0,0 @@
1
- """
2
- HF Spaces version of generate.py — same logic, paths adapted for /tmp/Wan2GP.
3
- Called as a subprocess from app.py inside @spaces.GPU.
4
- """
5
-
6
- import argparse
7
- import os
8
- import sys
9
- from pathlib import Path
10
-
11
- WAN2GP_ROOT = Path(os.environ.get("WAN2GP_ROOT", "/tmp/Wan2GP"))
12
-
13
- MODEL_SHORTHANDS = {
14
- "10eros": "ten_eros",
15
- }
16
-
17
- DEFAULTS = {
18
- "ten_eros": {
19
- "num_inference_steps": 8,
20
- "guidance_scale": 5.0,
21
- "resolution": "832x480",
22
- "video_length": 81,
23
- },
24
- }
25
-
26
-
27
- def p(*args, **kwargs):
28
- print(*args, **kwargs, flush=True)
29
-
30
-
31
- def parse_args():
32
- ap = argparse.ArgumentParser()
33
- ap.add_argument("--image", required=True)
34
- ap.add_argument("--prompt", required=True)
35
- ap.add_argument("--output", required=True)
36
- ap.add_argument("--model", default="10eros")
37
- ap.add_argument("--steps", type=int, default=None)
38
- ap.add_argument("--guidance_scale", type=float, default=None)
39
- ap.add_argument("--frames", type=int, default=None)
40
- ap.add_argument("--resolution", default=None)
41
- ap.add_argument("--seed", type=int, default=-1)
42
- return ap.parse_args()
43
-
44
-
45
- def main():
46
- args = parse_args()
47
-
48
- model_type = MODEL_SHORTHANDS.get(args.model, args.model)
49
- defaults = DEFAULTS.get(model_type, DEFAULTS["ten_eros"])
50
-
51
- image_path = str(Path(args.image.strip()).resolve())
52
- if not Path(image_path).exists():
53
- print(f"Fatal: image not found: {image_path}", flush=True)
54
- sys.exit(1)
55
-
56
- resolution = args.resolution or defaults["resolution"]
57
- if not args.resolution:
58
- try:
59
- from PIL import Image as _PIL
60
- img = _PIL.open(image_path)
61
- iw, ih = img.size
62
- if ih > iw:
63
- tw = 480
64
- th = round(ih / iw * tw / 32) * 32
65
- else:
66
- th = 480
67
- tw = round(iw / ih * th / 32) * 32
68
- resolution = f"{tw}x{th}"
69
- p(f"Auto-detected resolution: {resolution} (from {iw}x{ih} input)")
70
- except Exception:
71
- pass
72
-
73
- task = {
74
- "model_type": model_type,
75
- "base_model_type": model_type,
76
- "prompt": args.prompt,
77
- "image_start": image_path,
78
- "num_inference_steps": args.steps or defaults["num_inference_steps"],
79
- "guidance_scale": args.guidance_scale or defaults["guidance_scale"],
80
- "resolution": resolution,
81
- "video_length": args.frames or defaults["video_length"],
82
- "seed": args.seed,
83
- "image_prompt_type": "S",
84
- "input_video_strength": 1.0,
85
- "activated_loras": [
86
- "ltx-2.3-22b-distilled-lora-1.1_fro90_ceil72_condsafe.safetensors",
87
- ],
88
- "loras_multipliers": ["0.5"],
89
- }
90
-
91
- p(f"Model: {model_type}")
92
- p(f"Image: {image_path}")
93
- p(f"Steps: {task['num_inference_steps']} Guidance: {task['guidance_scale']}")
94
- p(f"Resolution: {task['resolution']} Frames: {task['video_length']}")
95
- p(f"Prompt: {args.prompt[:80]}")
96
-
97
- sys.path.insert(0, str(WAN2GP_ROOT))
98
- os.chdir(WAN2GP_ROOT)
99
-
100
- from shared.api import WanGPSession
101
-
102
- output_dir = Path(args.output).parent
103
- output_dir.mkdir(parents=True, exist_ok=True)
104
-
105
- p("Starting session...")
106
- session = WanGPSession(root=WAN2GP_ROOT, output_dir=output_dir, console_output=True)
107
-
108
- p("Running generation...")
109
- result = session.run_task(task)
110
-
111
- output_file = None
112
-
113
- if result.artifacts:
114
- src = result.artifacts[0].path
115
- if src and Path(src).exists():
116
- output_file = src
117
-
118
- # Fallback: scan the output dir for any video file Wan2GP may have written
119
- if output_file is None:
120
- candidates = sorted(output_dir.glob("**/*.mp4"), key=lambda f: f.stat().st_mtime, reverse=True)
121
- if candidates:
122
- output_file = str(candidates[0])
123
- p(f"Found output via dir scan: {output_file}")
124
-
125
- if output_file:
126
- import shutil
127
- shutil.copy2(output_file, args.output)
128
- p(f"Done: {args.output}")
129
- else:
130
- p(f"No output found in {output_dir}")
131
- if result.errors:
132
- p(f"Errors: {result.errors}")
133
- sys.exit(1)
134
-
135
- session.close()
136
-
137
-
138
- if __name__ == "__main__":
139
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10Eros/requirements.txt DELETED
@@ -1,74 +0,0 @@
1
- # HF Spaces runtime
2
- gradio>=6.0.0
3
- spaces
4
- huggingface_hub>=0.24.0
5
-
6
- # Wan2GP deps (from requirements.txt — all packages that install on Linux)
7
- mmgp==3.7.6
8
- diffusers==0.36.0
9
- transformers==4.54.0
10
- tokenizers>=0.20.3
11
- accelerate>=1.1.1
12
- tqdm
13
- imageio
14
- imageio-ffmpeg
15
- einops
16
- sentencepiece
17
- open_clip_torch>=2.29.0
18
- numpy==2.1.2
19
- num2words==0.5.14
20
- moviepy==1.0.3
21
- av
22
- ffmpeg-python
23
- pygame>=2.1.0
24
- sounddevice>=0.4.0
25
- soundfile
26
- mutagen
27
- pyloudnorm
28
- librosa==0.11.0
29
- speechbrain==1.0.3
30
- openai-whisper==20250625
31
- audio-separator==0.36.1
32
- pyannote.audio==3.3.2
33
- loguru
34
- dashscope
35
- s3tokenizer
36
- conformer==0.3.2
37
- spacy_pkuseg
38
- spacy
39
- opencv-python-headless>=4.12.0.88
40
- pycocotools
41
- segment-anything
42
- rembg==2.0.65
43
- onnxruntime>=1.20.0
44
- decord
45
- timm
46
- iopath>=0.1.10
47
- insightface==0.7.3
48
- facexlib==0.3.0
49
- vector_quantize_pytorch==1.27.19
50
- omegaconf
51
- hydra-core
52
- easydict
53
- torchdiffeq>=0.2.5
54
- tensordict>=0.6.1
55
- peft==0.17.0
56
- vector-quantize-pytorch
57
- matplotlib
58
- gguf==0.17.1
59
- flash-linear-attention==0.4.1
60
- ftfy
61
- piexif
62
- nvidia-ml-py
63
- misaki
64
- gitdb==4.0.12
65
- gitpython==3.1.45
66
- stringzilla==4.0.14
67
- xxhash
68
- munch
69
- wetext==0.1.2
70
- markdown
71
- Pillow
72
- safetensors
73
- https://github.com/deepbeepmeep/smplfitter/releases/download/v0.2.10/smplfitter-0.2.10-py3-none-any.whl
74
- https://github.com/deepbeepmeep/chumpy/releases/download/v0.71/chumpy-0.71-py3-none-any.whl