Spaces:
Running on Zero
Running on Zero
fix(pipeline): pass save_dir so generate_music writes a usable file path
Browse filesgenerate_music's audios[0]['path'] is empty string when save_dir is not
provided — only the in-memory tensor is returned. Gradio's output processing
then tried to read the empty path, resolved it against cwd, and crashed
with IsADirectoryError on the project root.
Pass save_dir=./output/ so the audio is written with the UUID filename
the AudioSaver chose. Also add a defensive tensor-fallback (soundfile.write)
in case generate_music ever returns an empty path despite save_dir being
provided.
Caught while running the live app end-to-end after the M1 GPU smoke
passed — the smoke happened to skip this code path because its mock
provided a path. The bug only surfaced with the real pipeline.
- ace_pipeline.py +35 -2
ace_pipeline.py
CHANGED
|
@@ -41,6 +41,7 @@ from pathlib import Path
|
|
| 41 |
|
| 42 |
_REPO_ROOT = Path(__file__).resolve().parent
|
| 43 |
_CHECKPOINTS_DIR = _REPO_ROOT / "checkpoints"
|
|
|
|
| 44 |
|
| 45 |
_DEFAULT_DIT_CONFIG = "acestep-v15-xl-sft"
|
| 46 |
_DEFAULT_LM_MODEL = "acestep-5Hz-lm-0.6B"
|
|
@@ -193,14 +194,46 @@ class ACEStepStudio:
|
|
| 193 |
seeds=[int(params.get("seed", 1))],
|
| 194 |
)
|
| 195 |
|
| 196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
|
| 198 |
if not result.success:
|
| 199 |
raise RuntimeError(f"ACE-Step generation failed: {result.error}")
|
| 200 |
if not result.audios:
|
| 201 |
raise RuntimeError("ACE-Step returned no audio outputs")
|
| 202 |
|
| 203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
|
| 206 |
_PIPELINE: ACEStepStudio | None = None # module-level lazy singleton
|
|
|
|
| 41 |
|
| 42 |
_REPO_ROOT = Path(__file__).resolve().parent
|
| 43 |
_CHECKPOINTS_DIR = _REPO_ROOT / "checkpoints"
|
| 44 |
+
_OUTPUT_DIR = _REPO_ROOT / "output"
|
| 45 |
|
| 46 |
_DEFAULT_DIT_CONFIG = "acestep-v15-xl-sft"
|
| 47 |
_DEFAULT_LM_MODEL = "acestep-5Hz-lm-0.6B"
|
|
|
|
| 194 |
seeds=[int(params.get("seed", 1))],
|
| 195 |
)
|
| 196 |
|
| 197 |
+
# generate_music only writes a file when save_dir is provided; otherwise
|
| 198 |
+
# result.audios[i]["path"] is empty and ["tensor"] holds the raw audio.
|
| 199 |
+
# Pass an explicit output dir so the path is always usable.
|
| 200 |
+
_OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
| 201 |
+
|
| 202 |
+
result = generate_music(
|
| 203 |
+
self._dit,
|
| 204 |
+
self._llm,
|
| 205 |
+
gen_params,
|
| 206 |
+
gen_config,
|
| 207 |
+
save_dir=str(_OUTPUT_DIR),
|
| 208 |
+
)
|
| 209 |
|
| 210 |
if not result.success:
|
| 211 |
raise RuntimeError(f"ACE-Step generation failed: {result.error}")
|
| 212 |
if not result.audios:
|
| 213 |
raise RuntimeError("ACE-Step returned no audio outputs")
|
| 214 |
|
| 215 |
+
audio = result.audios[0]
|
| 216 |
+
path = audio.get("path") or ""
|
| 217 |
+
if not path:
|
| 218 |
+
# generate_music returned an empty path despite save_dir being passed.
|
| 219 |
+
# Fall back to writing the in-memory tensor so callers always get a
|
| 220 |
+
# valid file path (Gradio cannot serve an empty path).
|
| 221 |
+
import soundfile as sf
|
| 222 |
+
|
| 223 |
+
tensor = audio.get("tensor")
|
| 224 |
+
if tensor is None:
|
| 225 |
+
raise RuntimeError("ACE-Step returned neither an audio path nor a tensor")
|
| 226 |
+
sample_rate = int(audio.get("sample_rate", 48000))
|
| 227 |
+
audio_format = advanced.get("audio_format", "wav")
|
| 228 |
+
fallback = _OUTPUT_DIR / f"{audio.get('key', 'fallback')}.{audio_format}"
|
| 229 |
+
data = tensor.detach().cpu().numpy()
|
| 230 |
+
# soundfile expects (frames, channels); acestep tensors are (channels, frames)
|
| 231 |
+
if data.ndim == 2 and data.shape[0] in (1, 2):
|
| 232 |
+
data = data.T
|
| 233 |
+
sf.write(str(fallback), data, sample_rate)
|
| 234 |
+
path = str(fallback)
|
| 235 |
+
|
| 236 |
+
return path
|
| 237 |
|
| 238 |
|
| 239 |
_PIPELINE: ACEStepStudio | None = None # module-level lazy singleton
|