Spaces:
Running on Zero
Running on Zero
Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -48,6 +48,7 @@ BUDGETS = {
|
|
| 48 |
"Fast 路 512": (512, 512 * 896),
|
| 49 |
}
|
| 50 |
DEFAULT_BUDGET = "Balanced 路 640"
|
|
|
|
| 51 |
OUTPUT_DIR = os.path.join(tempfile.gettempdir(), "bgswap-outputs")
|
| 52 |
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
| 53 |
|
|
@@ -329,11 +330,10 @@ def get_duration(request, steps, seed, **_):
|
|
| 329 |
sequence = (int(request["text_token_tags"].shape[0]) + reference_rows(references, num_frames)
|
| 330 |
+ target_rows(height, width, num_frames))
|
| 331 |
denoise = int(steps) * (STEP_LINEAR * sequence + STEP_QUADRATIC * sequence ** 2) * SAFETY
|
| 332 |
-
passes = 2 if request.get("harmonize") else 1 # harmonize adds a second (mask-drop) denoise + decode pass
|
| 333 |
encode = 5 + reference_rows(references, num_frames) * 1e-3
|
| 334 |
share = (height * width * num_frames) / DEFAULT_CANVAS_PIXELS
|
| 335 |
-
total = (PLACEMENT_ALLOWANCE + encode + SOURCE_ENCODE_PER_DEFAULT_CANVAS * share +
|
| 336 |
-
+
|
| 337 |
duration = max(MIN_GPU_DURATION, min(MAX_GPU_DURATION, int(total)))
|
| 338 |
print(f"[bgswap] S={sequence} -> reserving {duration}s ({denoise:.0f}s denoise at {steps} steps)", flush=True)
|
| 339 |
return duration
|
|
@@ -381,31 +381,21 @@ def _generate(request, steps, seed):
|
|
| 381 |
except Exception as error:
|
| 382 |
print(f"[bgswap] turbo switch failed ({type(error).__name__}: {error})", flush=True)
|
| 383 |
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
source_audio=source_audio, source_audio_sample_rate=sr, audio_mask=None,
|
| 392 |
-
height=request["height"], width=request["width"], num_frames=request["num_frames"],
|
| 393 |
-
num_inference_steps=int(steps), generator=torch.Generator("cpu").manual_seed(int(seed)))
|
| 394 |
-
|
| 395 |
-
state = one_pass(request["source_video"], request["mask"],
|
| 396 |
-
request["source_audio"], request["source_audio_sample_rate"])
|
| 397 |
-
audio, sr = state.get("audio"), state.get("sampling_rate")
|
| 398 |
-
videos = state.get("videos")[0]
|
| 399 |
-
|
| 400 |
if request.get("harmonize"):
|
| 401 |
-
#
|
| 402 |
-
#
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
return videos, None if audio is None else audio[0].cpu(), sr
|
| 409 |
|
| 410 |
|
| 411 |
def replace_background(clip, prompt, budget, steps, seed, keep_audio, harmonize=True, remove_only=False, progress=None):
|
|
|
|
| 48 |
"Fast 路 512": (512, 512 * 896),
|
| 49 |
}
|
| 50 |
DEFAULT_BUDGET = "Balanced 路 640"
|
| 51 |
+
HARMONIZE_DROP_FRAC = 0.5 # harmonize: drop the mask after this fraction of the denoise steps (midpoint)
|
| 52 |
OUTPUT_DIR = os.path.join(tempfile.gettempdir(), "bgswap-outputs")
|
| 53 |
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
| 54 |
|
|
|
|
| 330 |
sequence = (int(request["text_token_tags"].shape[0]) + reference_rows(references, num_frames)
|
| 331 |
+ target_rows(height, width, num_frames))
|
| 332 |
denoise = int(steps) * (STEP_LINEAR * sequence + STEP_QUADRATIC * sequence ** 2) * SAFETY
|
|
|
|
| 333 |
encode = 5 + reference_rows(references, num_frames) * 1e-3
|
| 334 |
share = (height * width * num_frames) / DEFAULT_CANVAS_PIXELS
|
| 335 |
+
total = (PLACEMENT_ALLOWANCE + encode + SOURCE_ENCODE_PER_DEFAULT_CANVAS * share + denoise
|
| 336 |
+
+ DECODE_BASE + DECODE_PER_DEFAULT_CANVAS * share + 10)
|
| 337 |
duration = max(MIN_GPU_DURATION, min(MAX_GPU_DURATION, int(total)))
|
| 338 |
print(f"[bgswap] S={sequence} -> reserving {duration}s ({denoise:.0f}s denoise at {steps} steps)", flush=True)
|
| 339 |
return duration
|
|
|
|
| 381 |
except Exception as error:
|
| 382 |
print(f"[bgswap] turbo switch failed ({type(error).__name__}: {error})", flush=True)
|
| 383 |
|
| 384 |
+
kwargs = dict(
|
| 385 |
+
prompt_embeds=request["prompt_embeds"].to("cuda"), text_token_tags=request["text_token_tags"],
|
| 386 |
+
references=build_references(request["references"]),
|
| 387 |
+
source_video=request["source_video"], source_fps=FPS, mask=request["mask"],
|
| 388 |
+
source_audio=request["source_audio"], source_audio_sample_rate=request["source_audio_sample_rate"],
|
| 389 |
+
audio_mask=None, height=request["height"], width=request["width"], num_frames=request["num_frames"],
|
| 390 |
+
num_inference_steps=int(steps), generator=torch.Generator("cpu").manual_seed(int(seed)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 391 |
if request.get("harmonize"):
|
| 392 |
+
# single pass: keep the mask until mask_drop_step, then free-refine the whole frame so the subject blends
|
| 393 |
+
# into the scene (the subject is re-noised to that step's level at the handoff). No second pass.
|
| 394 |
+
kwargs["mask_drop_step"] = max(1, min(int(steps) - 1, round(int(steps) * HARMONIZE_DROP_FRAC)))
|
| 395 |
+
|
| 396 |
+
state = PIPE(**kwargs)
|
| 397 |
+
audio = state.get("audio")
|
| 398 |
+
return state.get("videos")[0], None if audio is None else audio[0].cpu(), state.get("sampling_rate")
|
|
|
|
| 399 |
|
| 400 |
|
| 401 |
def replace_background(clip, prompt, budget, steps, seed, keep_audio, harmonize=True, remove_only=False, progress=None):
|