techfreakworm commited on
Commit
a30ec7c
·
unverified ·
1 Parent(s): 3a8ec98

feat(deploy): m7 — hf spaces readme + cache bootstrap + zerogpu decorator

Browse files
Files changed (4) hide show
  1. README.md +28 -28
  2. app.py +81 -12
  3. pyproject.toml +4 -0
  4. requirements.txt +4 -0
README.md CHANGED
@@ -1,29 +1,22 @@
1
  ---
2
  title: ACE Music Studio
3
- emoji: "🎵"
4
  colorFrom: gray
5
  colorTo: gray
6
  sdk: gradio
7
- sdk_version: "5.50.0"
8
  app_file: app.py
9
- python_version: "3.11"
10
- suggested_hardware: zero-a10g
11
- hf_oauth: false
12
  preload_from_hub:
13
- - ACE-Step/acestep-v15-xl-sft *.safetensors,config.json,scheduler/*,vae/*,tokenizer/*
14
- - Qwen/Qwen2.5-7B-Instruct *.safetensors,config.json,tokenizer*
15
- - facebook/htdemucs_ft *.th
16
  ---
17
 
18
  # ACE Music Studio
19
 
20
- A single-process Gradio app that wraps [ACE-Step 1.5 XL SFT](https://github.com/ace-step/ACE-Step-1.5) for full-song generation with vocals, with bundled Qwen 2.5 7B for lyrics and Demucs for stem separation. Runs locally on Apple Silicon (MPS+MLX) or NVIDIA (CUDA), deploys to Hugging Face Spaces (ZeroGPU).
21
-
22
- [![Spaces](https://img.shields.io/badge/%F0%9F%A4%97%20Spaces-Live-FFFFFF?style=flat-square)](https://huggingface.co/spaces/techfreakworm/ace-music-studio)
23
- [![GitHub stars](https://img.shields.io/github/stars/techfreakworm/ace-music-studio?style=flat-square)](https://github.com/techfreakworm/ace-music-studio/stargazers)
24
- [![License: MIT](https://img.shields.io/badge/License-MIT-FFFFFF?style=flat-square)](LICENSE)
25
- [![Python 3.11](https://img.shields.io/badge/Python-3.11-FFFFFF?style=flat-square&logo=python&logoColor=white)](pyproject.toml)
26
- [![Backed by ACE-Step](https://img.shields.io/badge/backend-ACE--Step%201.5%20XL%20SFT-FFFFFF?style=flat-square)](https://github.com/ace-step/ACE-Step-1.5)
27
 
28
  → **Live demo:** https://huggingface.co/spaces/techfreakworm/ace-music-studio
29
 
@@ -31,7 +24,7 @@ A single-process Gradio app that wraps [ACE-Step 1.5 XL SFT](https://github.com/
31
 
32
  ## What's inside
33
 
34
- Five tabs. One ACE-Step pipeline underneath. Progressive disclosure — defaults stay short and reveal advanced controls only when asked.
35
 
36
  | Mode | Inputs | What it does |
37
  |---|---|---|
@@ -41,38 +34,43 @@ Five tabs. One ACE-Step pipeline underneath. Progressive disclosure — defaults
41
  | **Edit** | source audio + segment + target lyrics | Repaint a segment OR flow-morph caption-to-caption |
42
  | **Lyrics** | brief + structure | Qwen 2.5 7B drafts structurally-tagged lyrics |
43
 
44
- Every song tab supports stacked LoRAs4 bundled presets (RapMachine, Chinese Rap, Lyric2Vocal, Text2Samples) plus arbitrary `.safetensors` uploads.
 
 
 
 
 
45
 
46
  ---
47
 
48
- ## Quick start (local)
49
 
50
- Requires **Python 3.11**, ~32 GB free disk for weights, and **128 GB unified memory recommended on Apple Silicon** (M5 Max ideal; M3 Max+ workable).
51
 
52
  ```bash
53
  git clone https://github.com/techfreakworm/ace-music-studio
54
  cd ace-music-studio
55
- bash setup.sh
56
  source .venv/bin/activate
57
- python app.py # http://127.0.0.1:7860
58
  ```
59
 
60
- First launch downloads the ACE-Step + Qwen + Demucs weights into your HF cache (`~/.cache/huggingface/hub/`). Subsequent starts are fast.
61
 
62
- **Apple Silicon notes:** `PYTORCH_ENABLE_MPS_FALLBACK=1` is set automatically by `app.py`. The Mac path uses the [`clockworksquirrel/ace-step-apple-silicon`](https://github.com/clockworksquirrel/ace-step-apple-silicon) fork for MLX-LM + MPS-DiT hybrid execution.
63
 
64
- ## Quick start (HF Spaces)
65
 
66
  ```bash
67
- git remote add space https://huggingface.co/spaces/techfreakworm/ace-music-studio
68
  git push space main
69
  ```
70
 
71
- `preload_from_hub` in this README pre-downloads ~32 GB of weights at build time. `app._bootstrap()` mirrors the read-only build cache into `~/hf-cache-rw/` then symlinks every snapshot into `./models/<repo>/` so the pipeline finds them locally on first request.
72
 
73
  ## Architecture
74
 
75
- See [`docs/superpowers/specs/2026-05-18-ace-music-studio-design.md`](docs/superpowers/specs/2026-05-18-ace-music-studio-design.md) for the full design. UI mockups live in [`docs/superpowers/specs/mockups/`](docs/superpowers/specs/mockups/).
76
 
77
  ## License
78
 
@@ -80,4 +78,6 @@ MIT for the app code (see `LICENSE`). ACE-Step 1.5 XL SFT, Qwen 2.5 7B Instruct,
80
 
81
  ## Credits
82
 
83
- ACE-Step by [ACE Studio × StepFun](https://ace-step.github.io/). Apple Silicon port by [clockworksquirrel](https://github.com/clockworksquirrel/ace-step-apple-silicon). Qwen 2.5 by [Alibaba](https://huggingface.co/Qwen). Demucs by [Meta AI](https://github.com/facebookresearch/demucs). Built by [@techfreakworm](https://huggingface.co/techfreakworm).
 
 
 
1
  ---
2
  title: ACE Music Studio
3
+ emoji: 🎵
4
  colorFrom: gray
5
  colorTo: gray
6
  sdk: gradio
7
+ sdk_version: 6.14.0
8
  app_file: app.py
9
+ pinned: false
10
+ license: mit
11
+ short_description: Open-source song generation studio on ACE-Step 1.5 XL SFT — Generate, Cover, Extend, Edit, draft Lyrics.
12
  preload_from_hub:
13
+ - ACE-Step/Ace-Step1.5 vae/diffusion_pytorch_model.safetensors,vae/config.json,encoder/pytorch_model.bin,encoder/config.json,encoder/tokenizer.json
14
+ - ACE-Step/acestep-v15-xl-sft model.safetensors
 
15
  ---
16
 
17
  # ACE Music Studio
18
 
19
+ A single-process Gradio app that wraps [ACE-Step 1.5 XL SFT](https://github.com/ace-step/ACE-Step-1.5) for full-song generation with vocals, with Qwen 2.5 for lyrics drafting and Demucs for stem separation. Runs locally on **Apple Silicon (MPS+MLX)** or **NVIDIA (CUDA)**, deploys to **Hugging Face Spaces (ZeroGPU)**.
 
 
 
 
 
 
20
 
21
  → **Live demo:** https://huggingface.co/spaces/techfreakworm/ace-music-studio
22
 
 
24
 
25
  ## What's inside
26
 
27
+ Five modes. One ACE-Step pipeline underneath. Progressive disclosure — defaults stay short and reveal advanced controls only when asked.
28
 
29
  | Mode | Inputs | What it does |
30
  |---|---|---|
 
34
  | **Edit** | source audio + segment + target lyrics | Repaint a segment OR flow-morph caption-to-caption |
35
  | **Lyrics** | brief + structure | Qwen 2.5 7B drafts structurally-tagged lyrics |
36
 
37
+ Every song mode supports a single stacked LoRA — bundled presets plus arbitrary `.safetensors` uploads. The preset registry ships with the official ACE-Step LoRAs published on HF:
38
+
39
+ - [ACE-Step/ACE-Step-v1-chinese-rap-LoRA](https://huggingface.co/ACE-Step/ACE-Step-v1-chinese-rap-LoRA)
40
+ - [ACE-Step/ACE-Step-v1.5-chinese-new-year-LoRA](https://huggingface.co/ACE-Step/ACE-Step-v1.5-chinese-new-year-LoRA)
41
+
42
+ After every song generation, three post-process actions sit beneath the player: **Demucs stem separation**, **pyloudnorm normalisation to -14 LUFS**, and **MP3 320k export via ffmpeg**.
43
 
44
  ---
45
 
46
+ ## Local setup
47
 
48
+ Requires **Python 3.11**, ~32 GB free disk for weights, and **128 GB unified memory recommended on Apple Silicon** (M5 Max ideal; M3 Max+ workable). On NVIDIA, ~24 GB VRAM.
49
 
50
  ```bash
51
  git clone https://github.com/techfreakworm/ace-music-studio
52
  cd ace-music-studio
53
+ bash setup.sh # creates .venv, installs requirements
54
  source .venv/bin/activate
55
+ python app.py # http://127.0.0.1:7860
56
  ```
57
 
58
+ `setup.sh` detects Apple Silicon and adds `requirements-mac.txt` (MLX-LM + the [`clockworksquirrel/ace-step-apple-silicon`](https://github.com/clockworksquirrel/ace-step-apple-silicon) fork). First launch downloads weights into your HF cache (`~/.cache/huggingface/hub/`).
59
 
60
+ `PYTORCH_ENABLE_MPS_FALLBACK=1` is set automatically by `app.py` so the few MPS-unsupported ops degrade to CPU.
61
 
62
+ ## HF Spaces deploy
63
 
64
  ```bash
65
+ git remote add space https://huggingface.co/spaces/<your-handle>/ace-music-studio
66
  git push space main
67
  ```
68
 
69
+ `preload_from_hub` (this README's frontmatter) pre-downloads the ACE-Step 1.5 XL SFT umbrella weights at build time. `app._bootstrap_spaces_cache()` runs once at module init when `SPACE_ID` is set, symlinking the HF cache into the fork's expected `<site-packages>/checkpoints/` layout so the pipeline finds them on first request. `@spaces.GPU(duration=180)` decorates the click handlers — on Spaces it gates them to a ZeroGPU worker, locally it's a no-op.
70
 
71
  ## Architecture
72
 
73
+ See [`docs/superpowers/specs/2026-05-18-ace-music-studio-design.md`](docs/superpowers/specs/2026-05-18-ace-music-studio-design.md) for the full design and [`docs/superpowers/plans/2026-05-18-ace-music-studio.md`](docs/superpowers/plans/2026-05-18-ace-music-studio.md) for the implementation plan.
74
 
75
  ## License
76
 
 
78
 
79
  ## Credits
80
 
81
+ ACE-Step by [ACE Studio × StepFun](https://ace-step.github.io/). Apple Silicon port by [clockworksquirrel](https://github.com/clockworksquirrel/ace-step-apple-silicon). Qwen 2.5 by [Alibaba](https://huggingface.co/Qwen). Demucs by [Meta AI](https://github.com/facebookresearch/demucs).
82
+
83
+ Made with ❤️ by [Mayank Gupta](https://huggingface.co/techfreakworm).
app.py CHANGED
@@ -28,9 +28,10 @@ state gives us the sidebar "active item" highlight for free via CSS
28
  DO NOT switch this back to ``gr.Tabs`` — that produces top-positioned
29
  horizontal tabs which contradicts the wireframes.
30
 
31
- On HF Spaces, ``_bootstrap()`` runs once on import to mirror the
32
- read-only preload cache into a writable tree. On Mac/Linux locally,
33
- it's a no-op until M7.
 
34
  """
35
 
36
  from __future__ import annotations
@@ -67,6 +68,78 @@ def get_backend() -> be.ACEStepStudioBackend:
67
  return _BACKEND
68
 
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  def _safe_call(fn, *args, **kwargs):
71
  """Wrap a mode handler so all known exceptions become friendly gr.Error toasts.
72
 
@@ -190,6 +263,7 @@ def on_lora_strength_change(state, strength: float):
190
  return new_state, _active_md(new_state["name"], float(strength), kind)
191
 
192
 
 
193
  def on_generate_click(
194
  prompt: str,
195
  lyrics: str,
@@ -218,6 +292,7 @@ def on_generate_click(
218
  return out_path, meta, new_history
219
 
220
 
 
221
  def on_cover_click(
222
  ref_audio,
223
  prompt: str,
@@ -249,6 +324,7 @@ def on_cover_click(
249
  return out_path, meta, new_history
250
 
251
 
 
252
  def on_extend_click(
253
  seed_audio,
254
  extra_prompt: str,
@@ -288,6 +364,7 @@ def on_extend_click(
288
  return out_path, meta, new_history
289
 
290
 
 
291
  def on_draft_lyrics(
292
  brief: str,
293
  structure: str,
@@ -365,6 +442,7 @@ def on_export_mp3(audio_path):
365
  return gr.File(value=str(out), visible=True)
366
 
367
 
 
368
  def on_edit_click(
369
  source_audio,
370
  sub_mode: str,
@@ -495,14 +573,6 @@ MODE_CHOICES = [
495
  ]
496
 
497
 
498
- def _bootstrap() -> None:
499
- """HF Spaces: mirror read-only preload cache into a writable tree.
500
-
501
- Local Mac/CUDA: no-op. Implemented at M7 when we wire deployment.
502
- """
503
- pass
504
-
505
-
506
  def build_app() -> gr.Blocks:
507
  device = ace_pipeline.detect_device()
508
 
@@ -762,7 +832,6 @@ def build_app() -> gr.Blocks:
762
 
763
 
764
  if __name__ == "__main__":
765
- _bootstrap()
766
  demo = build_app()
767
  demo.queue(default_concurrency_limit=1)
768
  demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))
 
28
  DO NOT switch this back to ``gr.Tabs`` — that produces top-positioned
29
  horizontal tabs which contradicts the wireframes.
30
 
31
+ On HF Spaces (``SPACE_ID`` env present), ``_bootstrap_spaces_cache()``
32
+ runs once on import to symlink HF hub cache snapshots into the
33
+ acestep-apple-silicon fork's ``<site-packages>/checkpoints/`` layout.
34
+ On Mac/Linux locally, it's a no-op.
35
  """
36
 
37
  from __future__ import annotations
 
68
  return _BACKEND
69
 
70
 
71
+ def _bootstrap_spaces_cache() -> None:
72
+ """On HF Spaces, mirror the HF hub cache into the site-packages checkpoints/ dir.
73
+
74
+ The acestep-apple-silicon fork resolves checkpoints relative to its own install
75
+ location (``.venv/.../site-packages/checkpoints/``). HF Spaces puts model weights
76
+ in the HF hub cache. This bootstrap snapshot-downloads the two required repos
77
+ into the cache (using preload mirror if available) and then symlinks each
78
+ snapshot child into ``checkpoints/`` so the fork's resolver finds them.
79
+
80
+ Local Mac/CUDA: no-op (guarded by ``SPACE_ID`` env var).
81
+ """
82
+ if not os.getenv("SPACE_ID"):
83
+ return
84
+
85
+ import site
86
+
87
+ from huggingface_hub import snapshot_download
88
+
89
+ site_pkgs = site.getsitepackages()[0]
90
+ target_dir = Path(site_pkgs) / "checkpoints"
91
+
92
+ if target_dir.exists():
93
+ return # already bootstrapped
94
+
95
+ hf_home = os.getenv("HF_HOME", "/home/user/.cache/huggingface")
96
+
97
+ # Download Ace-Step1.5 umbrella (vae + encoder).
98
+ umbrella_path = snapshot_download(
99
+ repo_id="ACE-Step/Ace-Step1.5",
100
+ cache_dir=hf_home,
101
+ )
102
+
103
+ # Download the XL SFT diffusion variant.
104
+ xl_sft_path = snapshot_download(
105
+ repo_id="ACE-Step/acestep-v15-xl-sft",
106
+ cache_dir=hf_home,
107
+ )
108
+
109
+ # Merge both snapshots into ``checkpoints/`` via symlinks.
110
+ target_dir.mkdir(parents=True, exist_ok=True)
111
+ for src_path in [umbrella_path, xl_sft_path]:
112
+ for child in Path(src_path).iterdir():
113
+ link = target_dir / child.name
114
+ if not link.exists():
115
+ link.symlink_to(child)
116
+
117
+
118
+ def _maybe_spaces_gpu():
119
+ """Return ``@spaces.GPU(duration=180)`` on HF Spaces, otherwise a no-op decorator.
120
+
121
+ The decorator MUST be applied at module load time — ZeroGPU's startup
122
+ analyzer doesn't see runtime decoration. Local dev is a transparent pass-through.
123
+ """
124
+ if os.getenv("SPACE_ID"):
125
+ try:
126
+ import spaces
127
+
128
+ return spaces.GPU(duration=180)
129
+ except ImportError:
130
+ pass
131
+
132
+ def _noop(fn):
133
+ return fn
134
+
135
+ return _noop
136
+
137
+
138
+ # Run cache bootstrap at module import so HF Spaces' startup analyzer sees
139
+ # the symlinks before the lazy backend singleton is constructed on first click.
140
+ _bootstrap_spaces_cache()
141
+
142
+
143
  def _safe_call(fn, *args, **kwargs):
144
  """Wrap a mode handler so all known exceptions become friendly gr.Error toasts.
145
 
 
263
  return new_state, _active_md(new_state["name"], float(strength), kind)
264
 
265
 
266
+ @_maybe_spaces_gpu()
267
  def on_generate_click(
268
  prompt: str,
269
  lyrics: str,
 
292
  return out_path, meta, new_history
293
 
294
 
295
+ @_maybe_spaces_gpu()
296
  def on_cover_click(
297
  ref_audio,
298
  prompt: str,
 
324
  return out_path, meta, new_history
325
 
326
 
327
+ @_maybe_spaces_gpu()
328
  def on_extend_click(
329
  seed_audio,
330
  extra_prompt: str,
 
364
  return out_path, meta, new_history
365
 
366
 
367
+ @_maybe_spaces_gpu()
368
  def on_draft_lyrics(
369
  brief: str,
370
  structure: str,
 
442
  return gr.File(value=str(out), visible=True)
443
 
444
 
445
+ @_maybe_spaces_gpu()
446
  def on_edit_click(
447
  source_audio,
448
  sub_mode: str,
 
573
  ]
574
 
575
 
 
 
 
 
 
 
 
 
576
  def build_app() -> gr.Blocks:
577
  device = ace_pipeline.detect_device()
578
 
 
832
 
833
 
834
  if __name__ == "__main__":
 
835
  demo = build_app()
836
  demo.queue(default_concurrency_limit=1)
837
  demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))
pyproject.toml CHANGED
@@ -10,6 +10,10 @@ requires-python = ">=3.11,<3.12"
10
  [tool.ruff]
11
  line-length = 110
12
  target-version = "py311"
 
 
 
 
13
 
14
  [tool.ruff.lint]
15
  select = ["E", "F", "I", "B", "UP", "RUF"]
 
10
  [tool.ruff]
11
  line-length = 110
12
  target-version = "py311"
13
+ # checkpoints/ holds downloaded model code shipped by upstream HF repos —
14
+ # linting third-party drop-ins isn't our concern. output/ and research/
15
+ # are runtime artefacts / scratch.
16
+ extend-exclude = ["checkpoints", "output", "research", ".venv"]
17
 
18
  [tool.ruff.lint]
19
  select = ["E", "F", "I", "B", "UP", "RUF"]
requirements.txt CHANGED
@@ -11,3 +11,7 @@ librosa>=0.10
11
  huggingface_hub>=0.25
12
  numpy>=1.26,<2
13
  ace-step @ git+https://github.com/ace-step/ACE-Step-1.5.git
 
 
 
 
 
11
  huggingface_hub>=0.25
12
  numpy>=1.26,<2
13
  ace-step @ git+https://github.com/ace-step/ACE-Step-1.5.git
14
+ # HF Spaces ZeroGPU. Do NOT pin — HF's ZeroGPU build injects its own version
15
+ # and a pin causes pip-resolve failure. Locally the `import spaces` in
16
+ # app._maybe_spaces_gpu() is wrapped in try/except so absence is fine.
17
+ spaces; sys_platform == "linux"