ghostai1 commited on
Commit
5dc8e4b
Β·
verified Β·
1 Parent(s): 02aff0d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -70
app.py CHANGED
@@ -1,28 +1,28 @@
1
  #!/usr/bin/env python3
2
  """
3
  GhostAI Music Generator β€” ZeroGPU Space
4
- β€’ Pulls facebook/musicgen-medium from the Hub (needs HF_TOKEN)
5
- β€’ Installs audiocraft==1.3.0 *at runtime* ( --no-deps ) to dodge spaCy/typer clash
6
- β€’ Decorated with @spaces.GPU so each call gets a transient GPU
7
  """
8
 
9
- # ── ZERO-GPU decorator must come BEFORE torch/CUDA ────────────────
10
- import spaces # β‘  import first
11
 
12
- # ── Standard libs ─────────────────────────────────────────────────
13
  import os, sys, gc, time, warnings, tempfile, subprocess, random
14
  import numpy as np, psutil
15
 
16
- # ── Torch (CPU wheels already in container; tensors move to GPU) ──
17
  import torch, torchaudio
18
 
19
- # ── Other deps ────────────────────────────────────────────────────
20
  import gradio as gr
21
  from pydub import AudioSegment
22
  from huggingface_hub import login
23
  from torch.cuda.amp import autocast
24
 
25
- # ── tiny shim for transformers on Torch <2.3 ──────────────────────
26
  if not hasattr(torch, "get_default_device"):
27
  torch.get_default_device = lambda: torch.device(
28
  "cuda" if torch.cuda.is_available() else "cpu"
@@ -31,49 +31,52 @@ if not hasattr(torch, "get_default_device"):
31
  warnings.filterwarnings("ignore")
32
  os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
33
 
34
- # ── 1. make sure audiocraft is present (no deps) ──────────────────
35
  try:
36
  from audiocraft.models import MusicGen
37
  except ModuleNotFoundError:
38
  print("πŸ”§ Installing audiocraft 1.3.0 (no-deps)…")
39
- subprocess.check_call([sys.executable, "-m", "pip", "install",
40
- "audiocraft==1.3.0", "--no-deps", "--quiet"])
 
41
  from audiocraft.models import MusicGen
42
 
43
- # ── 2. HF authentication ─────────────────────────────────────────
44
  HF_TOKEN = os.getenv("HF_TOKEN")
45
  if not HF_TOKEN:
46
- sys.exit("ERROR: Please add HF_TOKEN secret in your Space.")
47
  login(HF_TOKEN)
48
 
49
- # ── 3. load model from Hub ────────────────────────────────────────
50
- print("⏬ Loading facebook/musicgen-medium (first run β‰ˆβ€†6 GB)…")
51
  musicgen = MusicGen.get_pretrained("facebook/musicgen-medium")
52
  musicgen.to(torch.get_default_device())
53
  musicgen.set_generation_params(duration=10, two_step_cfg=False)
54
  SR = musicgen.sample_rate
55
 
56
- # ── 4. prompt helpers (two shown; add the rest as before) ─────────
57
- def _p(base,bpm,dr,syn,st,bass,gtr,db,dg,flow):
58
  stxt = f" with {st}" if st!="none" else flow.format(bpm=bpm)
59
- return (f"{base}{db if bass=='none' else ', '+bass}"
60
- f"{dg if gtr=='none' else ', '+gtr+' guitar riffs'}"
 
61
  f"{'' if dr=='none' else ', '+dr+' drums'}"
62
- f"{'' if syn=='none' else ', '+syn+' accents'}{stxt} at {bpm} BPM.")
 
63
 
64
- def set_red_hot_chili(bpm,dr,syn,st,bass,gtr):
65
- return _p("Instrumental funk rock",bpm,dr,syn,st,bass,gtr,
66
- ", groovy basslines",", syncopated guitar riffs",
67
- "{bpm} BPM funky flow" if bpm>120 else "groovy rhythmic flow")
68
 
69
- def set_nirvana_grunge(bpm,dr,syn,st,bass,gtr):
70
- return _p("Instrumental grunge",bpm,dr,syn,st,bass,gtr,
71
- ", melodic basslines",", raw distorted guitar riffs",
72
- "{bpm} BPM grungy pulse" if bpm>120 else "grungy rhythmic pulse")
73
 
74
- # (… add your remaining genre prompt functions unchanged …)
75
 
76
- # ── 5. audio FX helpers ───────────────────────────────────────────
77
  def apply_eq(seg): return seg.low_pass_filter(8000).high_pass_filter(80)
78
  def apply_fade(seg): return seg.fade_in(1000).fade_out(1000)
79
 
@@ -83,75 +86,84 @@ def log(stage=""):
83
  a = torch.cuda.memory_allocated()/1024**3
84
  r = torch.cuda.memory_reserved()/1024**3
85
  print(f"GPU alloc {a:.2f} GB reserved {r:.2f} GB")
86
- print(f"CPU {psutil.virtual_memory().percent}%")
87
 
88
- # ── 6. main generation API (ZeroGPU wrapper) ───────────────────────
89
  @spaces.GPU
90
  def generate(prompt,cfg,k,p,temp,
91
  total_len,chunk_len,xfade,
92
  bpm,dr,syn,step,bass,gtr):
 
93
  if not prompt.strip():
94
  return None, "⚠️ Empty prompt."
95
 
96
- total_len, chunk_len = int(total_len), max(5, min(int(chunk_len), 15))
97
- n_chunks = max(1, total_len // chunk_len)
98
- chunk_len = total_len / n_chunks
99
- overlap = min(1.0, xfade / 1000.0)
100
- render = chunk_len + overlap
101
- parts = []
 
 
102
  torch.manual_seed(42); np.random.seed(42)
103
 
104
  for i in range(n_chunks):
105
- log(f"chunk {i+1} start")
106
  musicgen.set_generation_params(duration=render,use_sampling=True,
107
  top_k=k,top_p=p,temperature=temp,cfg_coef=cfg)
108
  with torch.no_grad(), autocast():
109
  audio = musicgen.generate([prompt], progress=False)[0]
 
110
  audio = audio.cpu().float()
111
  if audio.dim()==1 or audio.shape[0]==1:
112
  audio = audio.repeat(2,1)
 
113
  with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
114
  torchaudio.save(tmp.name, audio, SR)
115
- parts.append(AudioSegment.from_wav(tmp.name))
116
  os.unlink(tmp.name)
117
- torch.cuda.empty_cache(); gc.collect(); log(f"chunk {i+1} done")
118
 
119
- track = parts[0]
120
- for seg in parts[1:]:
121
  track = track.append(seg, crossfade=xfade)
122
- track = track[:total_len*1000]
123
  track = apply_fade(apply_eq(track).normalize(headroom=-9.0))
124
 
125
- out_f = "output_cleaned.mp3"
126
- track.export(out_f, format="mp3", bitrate="128k",
127
  tags={"title":"GhostAI Track","artist":"GhostAI"})
128
- return out_f, "βœ… Done!"
129
 
130
  def clear_inputs():
131
  return ("",3.0,250,0.9,1.0,30,10,1000,
132
  120,"none","none","none","none","none")
133
 
134
- # ── 7. minimal Gradio 4 UI (add more buttons if needed) ───────────
135
  with gr.Blocks(css="body{background:#0A0A0A;color:#E0E0E0;font-family:'Orbitron',sans-serif}") as demo:
136
- gr.HTML("<h1 style='text-align:center'>πŸ‘» GhostAI MusicGen</h1>")
137
- prompt = gr.Textbox(lines=4, label="Prompt")
138
- with gr.Row():
139
- gr.Button("RHCP 🌢️").click(set_red_hot_chili,
140
- inputs=[gr.State(120),"none","none","none","none","none"],
141
- outputs=prompt)
142
- gr.Button("Nirvana 🎸").click(set_nirvana_grunge,
143
- inputs=[gr.State(120),"none","none","none","none","none"],
144
- outputs=prompt)
145
 
 
 
 
 
 
 
 
 
 
 
146
  cfg = gr.Slider(1,10,3,label="CFG")
147
- k = gr.Slider(10,500,250,step=10,label="Top-K")
148
- p = gr.Slider(0,1,0.9,step=0.05,label="Top-P")
149
- temp = gr.Slider(0.1,2,1,label="Temp")
150
- length= gr.Radio([30,60,90,120],value=30,label="Length")
151
- chunk = gr.Slider(5,15,10,label="Chunk")
152
- xfade = gr.Slider(100,2000,1000,label="Cross-fade")
 
153
  bpm = gr.Slider(60,180,120,label="BPM")
154
- drum = gr.Dropdown(["none","standard rock","funk groove","techno kick","jazz swing"],"none","Drum")
155
  synth = gr.Dropdown(["none","analog synth","digital pad","arpeggiated synth"],"none","Synth")
156
  steps = gr.Dropdown(["none","syncopated steps","steady steps","complex steps"],"none","Steps")
157
  bass = gr.Dropdown(["none","slap bass","deep bass","melodic bass"],"none","Bass")
@@ -159,13 +171,15 @@ with gr.Blocks(css="body{background:#0A0A0A;color:#E0E0E0;font-family:'Orbitron'
159
 
160
  gen = gr.Button("Generate πŸš€")
161
  clr = gr.Button("Clear 🧹")
162
- out = gr.Audio(type="filepath")
163
- status = gr.Textbox(interactive=False)
164
 
165
  gen.click(generate,
166
- [prompt,cfg,k,p,temp,length,chunk,xfade,bpm,drum,synth,steps,bass,gtr],
167
- [out,status])
 
168
  clr.click(clear_inputs, None,
169
- [prompt,cfg,k,p,temp,length,chunk,xfade,bpm,drum,synth,steps,bass,gtr])
 
170
 
171
  demo.launch(share=False)
 
1
  #!/usr/bin/env python3
2
  """
3
  GhostAI Music Generator β€” ZeroGPU Space
4
+ β€’ Each request grabs a transient GPU via Hugging Face ZeroGPU.
5
+ β€’ Model: facebook/musicgen-medium (downloaded with HF_TOKEN secret).
6
+ β€’ Runtime installs audiocraft==1.3.0 --no-deps to dodge spaCy/typer issues.
7
  """
8
 
9
+ # ── 0. ZeroGPU must be imported *before* torch is touched ──────────
10
+ import spaces # <-- DO NOT move this lower
11
 
12
+ # ── 1. Standard libs ───────────────────────────────────────────────
13
  import os, sys, gc, time, warnings, tempfile, subprocess, random
14
  import numpy as np, psutil
15
 
16
+ # ── 2. Torch stack (torch 2.1.0 & torchaudio 2.1.0 from requirements) ─
17
  import torch, torchaudio
18
 
19
+ # ── 3. UI / misc deps ─────────────────────────────────────────────
20
  import gradio as gr
21
  from pydub import AudioSegment
22
  from huggingface_hub import login
23
  from torch.cuda.amp import autocast
24
 
25
+ # ── 4. Torch <2.3 shim (transformers 4.38 calls get_default_device) ──
26
  if not hasattr(torch, "get_default_device"):
27
  torch.get_default_device = lambda: torch.device(
28
  "cuda" if torch.cuda.is_available() else "cpu"
 
31
  warnings.filterwarnings("ignore")
32
  os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
33
 
34
+ # ── 5. Install audiocraft at runtime (no deps) ─────────────────────
35
  try:
36
  from audiocraft.models import MusicGen
37
  except ModuleNotFoundError:
38
  print("πŸ”§ Installing audiocraft 1.3.0 (no-deps)…")
39
+ subprocess.check_call(
40
+ [sys.executable, "-m", "pip", "install", "audiocraft==1.3.0", "--no-deps", "-q"]
41
+ )
42
  from audiocraft.models import MusicGen
43
 
44
+ # ── 6. Hugging Face authentication ────────────────────────────────
45
  HF_TOKEN = os.getenv("HF_TOKEN")
46
  if not HF_TOKEN:
47
+ sys.exit("ERROR: Please add HF_TOKEN as a secret in your Space.")
48
  login(HF_TOKEN)
49
 
50
+ # ── 7. Load MusicGen model ────────────────────────────────────────
51
+ print("⏬ Loading facebook/musicgen-medium (first load β‰ˆ 6 GB)…")
52
  musicgen = MusicGen.get_pretrained("facebook/musicgen-medium")
53
  musicgen.to(torch.get_default_device())
54
  musicgen.set_generation_params(duration=10, two_step_cfg=False)
55
  SR = musicgen.sample_rate
56
 
57
+ # ── 8. Prompt builders (add more in same style) ───────────────────
58
+ def _build(base,bpm,dr,syn,st,bass,gtr,def_bass,def_gtr,flow):
59
  stxt = f" with {st}" if st!="none" else flow.format(bpm=bpm)
60
+ return (f"{base}"
61
+ f"{def_bass if bass=='none' else ', '+bass}"
62
+ f"{def_gtr if gtr=='none' else ', '+gtr+' guitar riffs'}"
63
  f"{'' if dr=='none' else ', '+dr+' drums'}"
64
+ f"{'' if syn=='none' else ', '+syn+' accents'}"
65
+ f"{stxt} at {bpm} BPM.")
66
 
67
+ def set_rhcp(bpm,dr,syn,st,bass,gtr):
68
+ return _build("Instrumental funk rock",bpm,dr,syn,st,bass,gtr,
69
+ ", groovy basslines",", syncopated guitar riffs",
70
+ "{bpm} BPM funky flow" if bpm>120 else "groovy rhythmic flow")
71
 
72
+ def set_nirvana(bpm,dr,syn,st,bass,gtr):
73
+ return _build("Instrumental grunge",bpm,dr,syn,st,bass,gtr,
74
+ ", melodic basslines",", raw distorted guitar riffs",
75
+ "{bpm} BPM grungy pulse" if bpm>120 else "grungy rhythmic pulse")
76
 
77
+ # (⚠️ Add your remaining genre functions here)
78
 
79
+ # ── 9. Audio post-FX helpers ──────────────────────────────────────
80
  def apply_eq(seg): return seg.low_pass_filter(8000).high_pass_filter(80)
81
  def apply_fade(seg): return seg.fade_in(1000).fade_out(1000)
82
 
 
86
  a = torch.cuda.memory_allocated()/1024**3
87
  r = torch.cuda.memory_reserved()/1024**3
88
  print(f"GPU alloc {a:.2f} GB reserved {r:.2f} GB")
89
+ print(f"CPU {psutil.virtual_memory().percent}% used")
90
 
91
+ # ── 10. Core generation (ZeroGPU decorator) ───────────────────────
92
  @spaces.GPU
93
  def generate(prompt,cfg,k,p,temp,
94
  total_len,chunk_len,xfade,
95
  bpm,dr,syn,step,bass,gtr):
96
+
97
  if not prompt.strip():
98
  return None, "⚠️ Empty prompt."
99
 
100
+ total_len = int(total_len)
101
+ chunk_len = max(5, min(int(chunk_len), 15))
102
+ n_chunks = max(1, total_len // chunk_len)
103
+ chunk_len = total_len / n_chunks
104
+ overlap = min(1.0, xfade / 1000.0)
105
+ render = chunk_len + overlap
106
+ segments = []
107
+
108
  torch.manual_seed(42); np.random.seed(42)
109
 
110
  for i in range(n_chunks):
111
+ log(f"chunk {i+1}")
112
  musicgen.set_generation_params(duration=render,use_sampling=True,
113
  top_k=k,top_p=p,temperature=temp,cfg_coef=cfg)
114
  with torch.no_grad(), autocast():
115
  audio = musicgen.generate([prompt], progress=False)[0]
116
+
117
  audio = audio.cpu().float()
118
  if audio.dim()==1 or audio.shape[0]==1:
119
  audio = audio.repeat(2,1)
120
+
121
  with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
122
  torchaudio.save(tmp.name, audio, SR)
123
+ segments.append(AudioSegment.from_wav(tmp.name))
124
  os.unlink(tmp.name)
125
+ torch.cuda.empty_cache(); gc.collect()
126
 
127
+ track = segments[0]
128
+ for seg in segments[1:]:
129
  track = track.append(seg, crossfade=xfade)
130
+ track = track[: total_len*1000]
131
  track = apply_fade(apply_eq(track).normalize(headroom=-9.0))
132
 
133
+ out_path = "output_cleaned.mp3"
134
+ track.export(out_path, format="mp3", bitrate="128k",
135
  tags={"title":"GhostAI Track","artist":"GhostAI"})
136
+ return out_path, "βœ… Done!"
137
 
138
  def clear_inputs():
139
  return ("",3.0,250,0.9,1.0,30,10,1000,
140
  120,"none","none","none","none","none")
141
 
142
+ # ── 11. Gradio Blocks UI ──────────────────────────────────────────
143
  with gr.Blocks(css="body{background:#0A0A0A;color:#E0E0E0;font-family:'Orbitron',sans-serif}") as demo:
144
+ gr.Markdown("<h1 style='text-align:center'>πŸ‘» GhostAI MusicGen</h1>")
145
+ prompt = gr.Textbox(lines=4, label="Instrumental Prompt")
 
 
 
 
 
 
 
146
 
147
+ with gr.Row():
148
+ gr.Button("RHCP 🌢️").click(set_rhcp,
149
+ inputs=[gr.State(120),"none","none","none","none","none"],
150
+ outputs=prompt)
151
+ gr.Button("Nirvana 🎸").click(set_nirvana,
152
+ inputs=[gr.State(120),"none","none","none","none","none"],
153
+ outputs=prompt)
154
+ # βž• Add more genre buttons here …
155
+
156
+ # Parameter controls
157
  cfg = gr.Slider(1,10,3,label="CFG")
158
+ top_k = gr.Slider(10,500,250,step=10,label="Top-K")
159
+ top_p = gr.Slider(0,1,0.9,step=0.05,label="Top-P")
160
+ temp = gr.Slider(0.1,2,1,label="Temperature")
161
+ length= gr.Radio([30,60,90,120],value=30,label="Length (s)")
162
+ chunk = gr.Slider(5,15,10,label="Chunk (s)")
163
+ xfade = gr.Slider(100,2000,1000,label="Cross-fade (ms)")
164
+
165
  bpm = gr.Slider(60,180,120,label="BPM")
166
+ drum = gr.Dropdown(["none","standard rock","funk groove","techno kick","jazz swing"],"none","Drums")
167
  synth = gr.Dropdown(["none","analog synth","digital pad","arpeggiated synth"],"none","Synth")
168
  steps = gr.Dropdown(["none","syncopated steps","steady steps","complex steps"],"none","Steps")
169
  bass = gr.Dropdown(["none","slap bass","deep bass","melodic bass"],"none","Bass")
 
171
 
172
  gen = gr.Button("Generate πŸš€")
173
  clr = gr.Button("Clear 🧹")
174
+ audio_out = gr.Audio(type="filepath")
175
+ status = gr.Textbox(interactive=False)
176
 
177
  gen.click(generate,
178
+ inputs=[prompt,cfg,top_k,top_p,temp,length,chunk,xfade,
179
+ bpm,drum,synth,steps,bass,gtr],
180
+ outputs=[audio_out,status])
181
  clr.click(clear_inputs, None,
182
+ [prompt,cfg,top_k,top_p,temp,length,chunk,xfade,
183
+ bpm,drum,synth,steps,bass,gtr])
184
 
185
  demo.launch(share=False)