linoyts HF Staff commited on
Commit
ea7e7be
·
verified ·
1 Parent(s): 554b731

native progress bar via generator (forwards on ZeroGPU)

Browse files
Files changed (1) hide show
  1. app.py +42 -12
app.py CHANGED
@@ -5,6 +5,8 @@ os.environ.setdefault("TORCHDYNAMO_DISABLE", "1")
5
 
6
  import random
7
  import tempfile
 
 
8
 
9
  import numpy as np
10
  import imageio.v3 as iio
@@ -46,11 +48,7 @@ pipe.to("cuda")
46
  pipe.vae.enable_tiling()
47
  _lora_path = hf_hub_download(LORA_REPO, LORA_FILE, token=HF_TOKEN)
48
  pipe.load_lora_weights(load_file(_lora_path), adapter_name="inpaint")
49
- pipe.fuse_lora(lora_scale=LORA_SCALE)
50
- pipe.unload_lora_weights()
51
- # AOTI: load precompiled transformer blocks at ROOT level (ZeroGPU loads on cuda at
52
- # module scope; do NOT lazy-load or move to cuda inside @spaces.GPU).
53
- spaces.aoti_load(module=pipe.transformer, repo_id="ltx-community/LTX-2.3-Transformer-GroupB-sm120-cu130-r0e")
54
 
55
 
56
  def _src_fps(path, default=FPS):
@@ -95,9 +93,38 @@ def _duration(*args, **kwargs):
95
  return int(70 + int(num_frames) * 1.3)
96
 
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  @spaces.GPU(duration=_duration)
99
  def outpaint(video, canvas_key, prompt, num_frames, seed, randomize,
100
- progress=gr.Progress(track_tqdm=True)):
101
  if video is None:
102
  raise gr.Error("Please upload a video.")
103
  if randomize:
@@ -133,11 +160,9 @@ def outpaint(video, canvas_key, prompt, num_frames, seed, randomize,
133
  desc = prompt.strip() or "the scene continues naturally beyond the original frame, consistent style and lighting"
134
  full_prompt = f"{desc}; seamlessly extend the scene into the empty margins, matching the existing content."
135
 
136
- def _cb(p, i, t, kw):
137
- progress((i + 1) / NUM_STEPS, desc=f"Outpainting — step {i + 1}/{NUM_STEPS}")
138
- return {}
139
 
140
- video_out, audio_out = pipe(
 
141
  prompt=full_prompt, negative_prompt="",
142
  reference_conditions=[LTX2ReferenceCondition(frames=ref, strength=1.0)],
143
  conditioning_attention_mask=attn_mask, reference_downscale_factor=1,
@@ -146,7 +171,12 @@ def outpaint(video, canvas_key, prompt, num_frames, seed, randomize,
146
  guidance_scale=1.0, stg_scale=0.0, audio_guidance_scale=1.0, audio_stg_scale=0.0,
147
  generator=torch.Generator(device="cuda").manual_seed(seed),
148
  output_type="np", return_dict=False, callback_on_step_end=_cb,
149
- )
 
 
 
 
 
150
 
151
  # keep the original pixels exactly in the center; use generated pixels in the margins (feathered).
152
  gen = (np.clip(video_out[0], 0, 1) * 255).astype(np.uint8)
@@ -161,7 +191,7 @@ def outpaint(video, canvas_key, prompt, num_frames, seed, randomize,
161
 
162
  out_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name
163
  _export(out, audio_out, out_path)
164
- return out_path, seed
165
 
166
 
167
  with gr.Blocks(title="LTX-2.3 Video Outpaint") as demo:
 
5
 
6
  import random
7
  import tempfile
8
+ import threading
9
+ import time
10
 
11
  import numpy as np
12
  import imageio.v3 as iio
 
48
  pipe.vae.enable_tiling()
49
  _lora_path = hf_hub_download(LORA_REPO, LORA_FILE, token=HF_TOKEN)
50
  pipe.load_lora_weights(load_file(_lora_path), adapter_name="inpaint")
51
+ pipe.set_adapters("inpaint", LORA_SCALE)
 
 
 
 
52
 
53
 
54
  def _src_fps(path, default=FPS):
 
93
  return int(70 + int(num_frames) * 1.3)
94
 
95
 
96
+
97
+ class StreamRun:
98
+ """Run pipe() in a thread; yield live status strings (generator yields DO forward on ZeroGPU)."""
99
+ def __init__(self, call_pipe, num_steps):
100
+ self.call_pipe, self.num_steps = call_pipe, num_steps
101
+ self.state = {"step": 0}
102
+ self.holder = {}
103
+ def _cb(self, p, i, t, kw):
104
+ self.state["step"] = i + 1
105
+ return {}
106
+ def _run(self):
107
+ try:
108
+ self.holder["out"] = self.call_pipe(self._cb)
109
+ except Exception as e:
110
+ self.holder["err"] = e
111
+ def stream(self):
112
+ th = threading.Thread(target=self._run); th.start()
113
+ while th.is_alive():
114
+ s = self.state["step"]
115
+ yield (s / self.num_steps if s else 0.0, f"step {s}/{self.num_steps}" if s else "Loading model…")
116
+ time.sleep(0.4)
117
+ th.join()
118
+ if "err" in self.holder:
119
+ raise self.holder["err"]
120
+ @property
121
+ def result(self):
122
+ return self.holder["out"]
123
+
124
+
125
  @spaces.GPU(duration=_duration)
126
  def outpaint(video, canvas_key, prompt, num_frames, seed, randomize,
127
+ progress=gr.Progress()):
128
  if video is None:
129
  raise gr.Error("Please upload a video.")
130
  if randomize:
 
160
  desc = prompt.strip() or "the scene continues naturally beyond the original frame, consistent style and lighting"
161
  full_prompt = f"{desc}; seamlessly extend the scene into the empty margins, matching the existing content."
162
 
 
 
 
163
 
164
+ def _call_pipe(_cb):
165
+ return pipe(
166
  prompt=full_prompt, negative_prompt="",
167
  reference_conditions=[LTX2ReferenceCondition(frames=ref, strength=1.0)],
168
  conditioning_attention_mask=attn_mask, reference_downscale_factor=1,
 
171
  guidance_scale=1.0, stg_scale=0.0, audio_guidance_scale=1.0, audio_stg_scale=0.0,
172
  generator=torch.Generator(device="cuda").manual_seed(seed),
173
  output_type="np", return_dict=False, callback_on_step_end=_cb,
174
+ )
175
+ runner = StreamRun(_call_pipe, NUM_STEPS)
176
+ for _frac, _desc in runner.stream():
177
+ progress(_frac, desc=_desc)
178
+ yield gr.update(), gr.update()
179
+ video_out, audio_out = runner.result
180
 
181
  # keep the original pixels exactly in the center; use generated pixels in the margins (feathered).
182
  gen = (np.clip(video_out[0], 0, 1) * 255).astype(np.uint8)
 
191
 
192
  out_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name
193
  _export(out, audio_out, out_path)
194
+ yield out_path, seed
195
 
196
 
197
  with gr.Blocks(title="LTX-2.3 Video Outpaint") as demo: