Spaces:
Running on Zero
Running on Zero
Commit ·
72d8940
1
Parent(s): d8ac0be
api: generate_inpaint mask_soft_s — the kept context fades out of the conditioning before the mask edge instead of stopping at a wall
Browse files
README.md
CHANGED
|
@@ -118,7 +118,7 @@ Argument order matters (positional):
|
|
| 118 |
|
| 119 |
- `/generate` — `token, model_variant, prompt, negative_prompt, seconds, steps, cfg_scale, seed`
|
| 120 |
- `/generate_a2a` — `token, model_variant, init_audio, prompt, negative_prompt, init_noise_level, seconds, steps, cfg_scale, seed`
|
| 121 |
-
- `/generate_inpaint` — `token, model_variant, inpaint_audio, prompt, negative_prompt, mask_start_s, mask_end_s, seconds, steps, cfg_scale, seed, init_noise_level` — keeps `inpaint_audio` outside `[mask_start_s, mask_end_s]` and regenerates inside (mask_end_s 0 = to the end). Continuation: pass the previous chunk's last N seconds followed by silence, mask_start_s = N. `init_noise_level` 0 = pure inpaint; > 0 also seeds the whole clip from the same audio.
|
| 122 |
|
| 123 |
`seed = -1` picks a random one; the seed actually used comes back in `meta`.
|
| 124 |
Inputs are clamped server-side (seconds per-model cap, steps 1–100, cfg 0–15).
|
|
|
|
| 118 |
|
| 119 |
- `/generate` — `token, model_variant, prompt, negative_prompt, seconds, steps, cfg_scale, seed`
|
| 120 |
- `/generate_a2a` — `token, model_variant, init_audio, prompt, negative_prompt, init_noise_level, seconds, steps, cfg_scale, seed`
|
| 121 |
+
- `/generate_inpaint` — `token, model_variant, inpaint_audio, prompt, negative_prompt, mask_start_s, mask_end_s, seconds, steps, cfg_scale, seed, init_noise_level` — keeps `inpaint_audio` outside `[mask_start_s, mask_end_s]` and regenerates inside (mask_end_s 0 = to the end). Continuation: pass the previous chunk's last N seconds followed by silence, mask_start_s = N. `init_noise_level` 0 = pure inpaint; > 0 also seeds the whole clip from the same audio. Optional 13th arg `mask_soft_s`: the kept context fades out of the conditioning over that many seconds before `mask_start_s` (0 = hard edge).
|
| 122 |
|
| 123 |
`seed = -1` picks a random one; the seed actually used comes back in `meta`.
|
| 124 |
Inputs are clamped server-side (seconds per-model cap, steps 1–100, cfg 0–15).
|
app.py
CHANGED
|
@@ -263,7 +263,8 @@ def _generate(variant_key: str,
|
|
| 263 |
init_noise_level: Optional[float] = None,
|
| 264 |
inpaint_audio_path: Optional[str] = None,
|
| 265 |
mask_start_s: Optional[float] = None,
|
| 266 |
-
mask_end_s: Optional[float] = None
|
|
|
|
| 267 |
"""Returns (wav_path, meta). Inputs must already be clamped.
|
| 268 |
inpaint_audio_path + mask_start_s/mask_end_s: the audio is kept verbatim
|
| 269 |
outside [mask_start_s, mask_end_s] and regenerated inside it (that is how
|
|
@@ -305,8 +306,24 @@ def _generate(variant_key: str,
|
|
| 305 |
model_dtype = next(lv.model.parameters()).dtype
|
| 306 |
gen_kwargs["inpaint_audio"] = _load_init_audio(
|
| 307 |
inpaint_audio_path, lv.sample_rate, model_dtype)
|
| 308 |
-
|
| 309 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
|
| 311 |
output = generate_diffusion_cond_inpaint(lv.model, **gen_kwargs)
|
| 312 |
output = rearrange(output, "b d n -> d (b n)")
|
|
@@ -334,6 +351,7 @@ def _generate(variant_key: str,
|
|
| 334 |
init_noise_level if init_noise_level is not None else 0.4)
|
| 335 |
if inpaint_audio_path:
|
| 336 |
meta["inpaint_mask_s"] = [float(mask_start_s), float(mask_end_s)]
|
|
|
|
| 337 |
print(f"[gen] {meta}", flush=True)
|
| 338 |
return out_path, meta
|
| 339 |
|
|
@@ -408,14 +426,14 @@ def api_generate_a2a(token, variant_key, init_audio, prompt, negative_prompt,
|
|
| 408 |
|
| 409 |
def _api_duration_inpaint(token, variant_key, inpaint_audio, prompt, negative_prompt,
|
| 410 |
mask_start_s, mask_end_s, seconds, steps, cfg_scale, seed,
|
| 411 |
-
init_noise_level):
|
| 412 |
return _gpu_seconds(seconds)
|
| 413 |
|
| 414 |
|
| 415 |
@spaces.GPU(duration=_api_duration_inpaint)
|
| 416 |
def api_generate_inpaint(token, variant_key, inpaint_audio, prompt, negative_prompt,
|
| 417 |
mask_start_s, mask_end_s, seconds, steps, cfg_scale, seed,
|
| 418 |
-
init_noise_level):
|
| 419 |
"""Keep inpaint_audio outside [mask_start_s, mask_end_s], regenerate inside.
|
| 420 |
For continuation: inpaint_audio = the previous chunk's tail followed by
|
| 421 |
anything (silence is fine) up to `seconds`; mask_start_s = tail length,
|
|
@@ -432,7 +450,8 @@ def api_generate_inpaint(token, variant_key, inpaint_audio, prompt, negative_pro
|
|
| 432 |
if me <= ms:
|
| 433 |
raise gr.Error("mask_end_s must be greater than mask_start_s.")
|
| 434 |
noise = float(init_noise_level or 0.0)
|
| 435 |
-
|
|
|
|
| 436 |
if noise > 0:
|
| 437 |
kw.update(init_audio_path=inpaint_audio, init_noise_level=max(0.0, min(noise, 1.0)))
|
| 438 |
path, meta = _generate(key, prompt, negative_prompt, seconds, steps, cfg_scale, seed, **kw)
|
|
@@ -1042,13 +1061,14 @@ with gr.Blocks(theme=gr.themes.Citrus(), title="abv1 sa3 engine") as demo:
|
|
| 1042 |
_i_cfg = gr.Number(value=1.0, label="cfg_scale")
|
| 1043 |
_i_seed = gr.Number(value=-1, label="seed")
|
| 1044 |
_i_noise = gr.Number(value=0, label="init_noise_level (0 = pure inpaint)")
|
|
|
|
| 1045 |
_i_file = gr.File(label="audio out")
|
| 1046 |
_i_json = gr.JSON(label="meta")
|
| 1047 |
_i_btn = gr.Button("generate_inpaint")
|
| 1048 |
_i_btn.click(
|
| 1049 |
fn=api_generate_inpaint,
|
| 1050 |
inputs=[_i_token, _i_variant, _i_audio, _i_prompt, _i_negative,
|
| 1051 |
-
_i_ms, _i_me, _i_seconds, _i_steps, _i_cfg, _i_seed, _i_noise],
|
| 1052 |
outputs=[_i_file, _i_json],
|
| 1053 |
api_name="generate_inpaint",
|
| 1054 |
show_progress="hidden",
|
|
|
|
| 263 |
init_noise_level: Optional[float] = None,
|
| 264 |
inpaint_audio_path: Optional[str] = None,
|
| 265 |
mask_start_s: Optional[float] = None,
|
| 266 |
+
mask_end_s: Optional[float] = None,
|
| 267 |
+
mask_soft_s: float = 0.0) -> tuple[str, dict]:
|
| 268 |
"""Returns (wav_path, meta). Inputs must already be clamped.
|
| 269 |
inpaint_audio_path + mask_start_s/mask_end_s: the audio is kept verbatim
|
| 270 |
outside [mask_start_s, mask_end_s] and regenerated inside it (that is how
|
|
|
|
| 306 |
model_dtype = next(lv.model.parameters()).dtype
|
| 307 |
gen_kwargs["inpaint_audio"] = _load_init_audio(
|
| 308 |
inpaint_audio_path, lv.sample_rate, model_dtype)
|
| 309 |
+
if mask_soft_s and mask_soft_s > 0:
|
| 310 |
+
# Soft edge: the kept context fades out of the conditioning over
|
| 311 |
+
# mask_soft_s before mask_start_s instead of stopping at a wall.
|
| 312 |
+
# The library multiplies the encoded audio by this mask (fractional
|
| 313 |
+
# values propagate; nearest-neighbour resize to latent frames).
|
| 314 |
+
n = lv.sample_size
|
| 315 |
+
m = torch.ones(1, n, device="cuda")
|
| 316 |
+
a = int(float(mask_start_s) * lv.sample_rate)
|
| 317 |
+
b = int(float(mask_end_s) * lv.sample_rate)
|
| 318 |
+
m[:, a:b] = 0.0
|
| 319 |
+
r = int(float(mask_soft_s) * lv.sample_rate)
|
| 320 |
+
r0 = max(0, a - r)
|
| 321 |
+
if a > r0:
|
| 322 |
+
m[:, r0:a] = torch.linspace(1.0, 0.0, a - r0, device="cuda")
|
| 323 |
+
gen_kwargs["inpaint_mask"] = m
|
| 324 |
+
else:
|
| 325 |
+
gen_kwargs["inpaint_mask_start_seconds"] = float(mask_start_s)
|
| 326 |
+
gen_kwargs["inpaint_mask_end_seconds"] = float(mask_end_s)
|
| 327 |
|
| 328 |
output = generate_diffusion_cond_inpaint(lv.model, **gen_kwargs)
|
| 329 |
output = rearrange(output, "b d n -> d (b n)")
|
|
|
|
| 351 |
init_noise_level if init_noise_level is not None else 0.4)
|
| 352 |
if inpaint_audio_path:
|
| 353 |
meta["inpaint_mask_s"] = [float(mask_start_s), float(mask_end_s)]
|
| 354 |
+
meta["mask_soft_s"] = float(mask_soft_s or 0.0)
|
| 355 |
print(f"[gen] {meta}", flush=True)
|
| 356 |
return out_path, meta
|
| 357 |
|
|
|
|
| 426 |
|
| 427 |
def _api_duration_inpaint(token, variant_key, inpaint_audio, prompt, negative_prompt,
|
| 428 |
mask_start_s, mask_end_s, seconds, steps, cfg_scale, seed,
|
| 429 |
+
init_noise_level, mask_soft_s=0):
|
| 430 |
return _gpu_seconds(seconds)
|
| 431 |
|
| 432 |
|
| 433 |
@spaces.GPU(duration=_api_duration_inpaint)
|
| 434 |
def api_generate_inpaint(token, variant_key, inpaint_audio, prompt, negative_prompt,
|
| 435 |
mask_start_s, mask_end_s, seconds, steps, cfg_scale, seed,
|
| 436 |
+
init_noise_level, mask_soft_s=0):
|
| 437 |
"""Keep inpaint_audio outside [mask_start_s, mask_end_s], regenerate inside.
|
| 438 |
For continuation: inpaint_audio = the previous chunk's tail followed by
|
| 439 |
anything (silence is fine) up to `seconds`; mask_start_s = tail length,
|
|
|
|
| 450 |
if me <= ms:
|
| 451 |
raise gr.Error("mask_end_s must be greater than mask_start_s.")
|
| 452 |
noise = float(init_noise_level or 0.0)
|
| 453 |
+
soft = max(0.0, min(float(mask_soft_s or 0.0), ms))
|
| 454 |
+
kw = dict(inpaint_audio_path=inpaint_audio, mask_start_s=ms, mask_end_s=me, mask_soft_s=soft)
|
| 455 |
if noise > 0:
|
| 456 |
kw.update(init_audio_path=inpaint_audio, init_noise_level=max(0.0, min(noise, 1.0)))
|
| 457 |
path, meta = _generate(key, prompt, negative_prompt, seconds, steps, cfg_scale, seed, **kw)
|
|
|
|
| 1061 |
_i_cfg = gr.Number(value=1.0, label="cfg_scale")
|
| 1062 |
_i_seed = gr.Number(value=-1, label="seed")
|
| 1063 |
_i_noise = gr.Number(value=0, label="init_noise_level (0 = pure inpaint)")
|
| 1064 |
+
_i_soft = gr.Number(value=0, label="mask_soft_s (context fades out over this many s before mask_start_s; 0 = hard edge)")
|
| 1065 |
_i_file = gr.File(label="audio out")
|
| 1066 |
_i_json = gr.JSON(label="meta")
|
| 1067 |
_i_btn = gr.Button("generate_inpaint")
|
| 1068 |
_i_btn.click(
|
| 1069 |
fn=api_generate_inpaint,
|
| 1070 |
inputs=[_i_token, _i_variant, _i_audio, _i_prompt, _i_negative,
|
| 1071 |
+
_i_ms, _i_me, _i_seconds, _i_steps, _i_cfg, _i_seed, _i_noise, _i_soft],
|
| 1072 |
outputs=[_i_file, _i_json],
|
| 1073 |
api_name="generate_inpaint",
|
| 1074 |
show_progress="hidden",
|