Switch to musicgen-medium for cleaner continuations
Browse filesmusicgen-small's audio continuations degrade into noise after a chunk or two: text-only chunks stay clean (spectral flatness ~0.1) but every audio-seeded continuation is ~3x noisier (~0.3) regardless of guidance_scale or seed normalization. Swap to musicgen-medium, which continues more cleanly. Model id is now the LOFINITY_MUSICGEN env var (default facebook/musicgen-medium). Widen the @spaces.GPU duration budget to 40 + 40*chunks and bump the progress estimate, since medium renders slower and an overrun gets the brew KILLED mid-render.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
app.py
CHANGED
|
@@ -70,6 +70,10 @@ print(
|
|
| 70 |
)
|
| 71 |
|
| 72 |
ENGINE = os.getenv("LOFINITY_ENGINE", "musicgen")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
# 30s is musicgen-small's single-shot max (1500 tokens). Longer tapes are
|
| 74 |
# stitched from 30s chunks: each one re-seeds the model with the last OVERLAP_S
|
| 75 |
# of the track so it keeps playing from there. musicgen-small's context is 2048
|
|
@@ -86,7 +90,7 @@ OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "llama3.2:3b")
|
|
| 86 |
# read real per-chunk progress from it; it reports a time-based estimate from this
|
| 87 |
# rough per-length budget instead (tunable; only affects the cosmetic brew bar).
|
| 88 |
GPU_WARMUP_S = 5.0 # enrichment + cold-start/queue allowance before audio flows
|
| 89 |
-
GPU_SECS_PER_CHUNK =
|
| 90 |
|
| 91 |
app = Server(title="LoFinity")
|
| 92 |
|
|
@@ -267,7 +271,8 @@ _musicgen_lock = threading.Lock()
|
|
| 267 |
|
| 268 |
|
| 269 |
def load_musicgen():
|
| 270 |
-
"""Lazy-load MusicGen once; first call downloads
|
|
|
|
| 271 |
global _musicgen
|
| 272 |
with _musicgen_lock:
|
| 273 |
if _musicgen is None:
|
|
@@ -284,11 +289,9 @@ def load_musicgen():
|
|
| 284 |
device = "mps"
|
| 285 |
else:
|
| 286 |
device = "cpu"
|
| 287 |
-
print(f"[lofinity] loading
|
| 288 |
-
processor = AutoProcessor.from_pretrained(
|
| 289 |
-
model = MusicgenForConditionalGeneration.from_pretrained(
|
| 290 |
-
"facebook/musicgen-small"
|
| 291 |
-
)
|
| 292 |
model.to(device)
|
| 293 |
model.eval()
|
| 294 |
_musicgen = (processor, model, device)
|
|
@@ -422,7 +425,10 @@ def _gpu_budget(prompt: str, seconds: int = CHUNK_S) -> int:
|
|
| 422 |
better queue priority; the signature must mirror gpu_brew so ZeroGPU can pass
|
| 423 |
it the same args."""
|
| 424 |
chunks = max(1, round(int(seconds) / CHUNK_S))
|
| 425 |
-
|
|
|
|
|
|
|
|
|
|
| 426 |
|
| 427 |
|
| 428 |
@spaces.GPU(duration=_gpu_budget)
|
|
|
|
| 70 |
)
|
| 71 |
|
| 72 |
ENGINE = os.getenv("LOFINITY_ENGINE", "musicgen")
|
| 73 |
+
# musicgen-medium continues from an audio seed more cleanly than -small, whose
|
| 74 |
+
# continuations degrade into noise after a chunk or two. Override via the env to
|
| 75 |
+
# fall back to facebook/musicgen-small (faster, smaller) if needed.
|
| 76 |
+
MUSICGEN_MODEL = os.getenv("LOFINITY_MUSICGEN", "facebook/musicgen-medium")
|
| 77 |
# 30s is musicgen-small's single-shot max (1500 tokens). Longer tapes are
|
| 78 |
# stitched from 30s chunks: each one re-seeds the model with the last OVERLAP_S
|
| 79 |
# of the track so it keeps playing from there. musicgen-small's context is 2048
|
|
|
|
| 90 |
# read real per-chunk progress from it; it reports a time-based estimate from this
|
| 91 |
# rough per-length budget instead (tunable; only affects the cosmetic brew bar).
|
| 92 |
GPU_WARMUP_S = 5.0 # enrichment + cold-start/queue allowance before audio flows
|
| 93 |
+
GPU_SECS_PER_CHUNK = 25.0 # rough GPU render time per 30s chunk (musicgen-medium)
|
| 94 |
|
| 95 |
app = Server(title="LoFinity")
|
| 96 |
|
|
|
|
| 271 |
|
| 272 |
|
| 273 |
def load_musicgen():
|
| 274 |
+
"""Lazy-load MusicGen once; the first call downloads the model from the Hub
|
| 275 |
+
(musicgen-medium is ~3.5 GB)."""
|
| 276 |
global _musicgen
|
| 277 |
with _musicgen_lock:
|
| 278 |
if _musicgen is None:
|
|
|
|
| 289 |
device = "mps"
|
| 290 |
else:
|
| 291 |
device = "cpu"
|
| 292 |
+
print(f"[lofinity] loading {MUSICGEN_MODEL} on {device}…")
|
| 293 |
+
processor = AutoProcessor.from_pretrained(MUSICGEN_MODEL)
|
| 294 |
+
model = MusicgenForConditionalGeneration.from_pretrained(MUSICGEN_MODEL)
|
|
|
|
|
|
|
| 295 |
model.to(device)
|
| 296 |
model.eval()
|
| 297 |
_musicgen = (processor, model, device)
|
|
|
|
| 425 |
better queue priority; the signature must mirror gpu_brew so ZeroGPU can pass
|
| 426 |
it the same args."""
|
| 427 |
chunks = max(1, round(int(seconds) / CHUNK_S))
|
| 428 |
+
# musicgen-medium renders slower than -small, so budget generously — a brew
|
| 429 |
+
# that overruns its @spaces.GPU duration is KILLED mid-render; over-budgeting
|
| 430 |
+
# only costs quota, under-budgeting loses the tape.
|
| 431 |
+
return 40 + 40 * chunks # 30s->80, 60s->120, 90s->160
|
| 432 |
|
| 433 |
|
| 434 |
@spaces.GPU(duration=_gpu_budget)
|