ghostai1 commited on
Commit
2c690c6
Β·
verified Β·
1 Parent(s): a17b367

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +369 -503
app.py CHANGED
@@ -1,596 +1,462 @@
 
 
 
 
 
 
 
 
 
 
1
  import os
2
- import torch
3
- import torchaudio
4
- import psutil
5
- import time
6
  import sys
7
- import numpy as np
8
  import gc
 
 
 
 
 
 
 
 
9
  import gradio as gr
10
  from pydub import AudioSegment
11
- from audiocraft.models import MusicGen
12
  from torch.cuda.amp import autocast
13
- import warnings
14
- import random
15
  from huggingface_hub import login
16
- import tempfile
17
 
18
- # Suppress warnings for cleaner output
 
 
 
 
 
 
 
 
 
 
19
  warnings.filterwarnings("ignore")
20
-
21
- # Set PYTORCH_CUDA_ALLOC_CONF to manage memory fragmentation
22
  os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
23
 
24
- # Authenticate with Hugging Face
 
 
25
  hf_token = os.getenv("HF_TOKEN")
26
  if not hf_token:
27
- print("ERROR: HF_TOKEN environment variable not set. Please set it in the Hugging Face Space settings.")
28
  sys.exit(1)
 
29
  try:
30
  login(hf_token)
31
  except Exception as e:
32
  print(f"ERROR: Failed to authenticate with Hugging Face: {e}")
33
  sys.exit(1)
34
 
35
- # Check critical dependencies
 
 
36
  if np.__version__ != "1.23.5":
37
- print(f"WARNING: NumPy version {np.__version__} is being used. Tested with numpy==1.23.5.")
38
  if not torch.__version__.startswith("2.3.1"):
39
- print(f"WARNING: PyTorch version {torch.__version__} may not be compatible. Expected torch==2.3.1.")
40
 
41
- # 1) DEVICE SETUP WITH ENHANCED DEBUGGING
42
- print("Debugging GPU and CUDA setup...")
 
 
43
  print(f"PyTorch CUDA available: {torch.cuda.is_available()}")
44
  if torch.cuda.is_available():
45
- print(f"CUDA device count: {torch.cuda.device_count()}")
46
- print(f"CUDA current device: {torch.cuda.current_device()}")
47
- print(f"CUDA device name: {torch.cuda.get_device_name(0)}")
48
- print(f"CUDA version: {torch.version.cuda}")
49
  else:
50
- print("WARNING: CUDA is not available. Checking for potential issues...")
51
- print(f"CUDA library loaded: {torch._C._cuda_getCompiledVersion() > 0}")
52
- print("Please ensure the Hugging Face Space is configured to use a GPU runtime.")
53
- print("Falling back to CPU rendering. Note: Performance may be significantly slower.")
54
 
55
  device = "cuda" if torch.cuda.is_available() else "cpu"
56
- if device != "cuda":
57
- print("WARNING: Running on CPU. This is a fallback due to CUDA unavailability. GPU rendering is strongly recommended for performance.")
58
 
59
- # Pre-run memory cleanup
60
  if device == "cuda":
61
  torch.cuda.empty_cache()
62
  gc.collect()
63
  torch.cuda.ipc_collect()
64
  torch.cuda.synchronize()
65
 
66
- # 2) LOAD MUSICGEN INTO VRAM
 
 
67
  try:
68
- print("Loading MusicGen medium model from Hugging Face...")
69
  musicgen_model = MusicGen.get_pretrained("facebook/musicgen-medium", device=device)
70
- musicgen_model.set_generation_params(
71
- duration=10, # Default chunk duration
72
- two_step_cfg=False # Disable two-step CFG for stability
73
- )
74
  except Exception as e:
75
  print(f"ERROR: Failed to load MusicGen model: {e}")
76
- print("Ensure you have access to facebook/musicgen-medium and a valid HF_TOKEN.")
77
  sys.exit(1)
78
 
79
- # 3) RESOURCE MONITORING FUNCTION
 
 
80
  def print_resource_usage(stage: str):
81
  print(f"--- {stage} ---")
82
  if device == "cuda":
83
  print(f"GPU Memory Allocated: {torch.cuda.memory_allocated() / (1024**3):.2f} GB")
84
- print(f"GPU Memory Reserved: {torch.cuda.memory_reserved() / (1024**3):.2f} GB")
85
- print(f"CPU Memory Used: {psutil.virtual_memory().percent}%")
86
- print("---------------")
87
 
88
- # Check available GPU memory if using CUDA
89
- def check_vram_availability(required_gb=3.5):
90
  if device != "cuda":
91
- print("Skipping VRAM check as running on CPU.")
92
  return True
93
- total_vram = torch.cuda.get_device_properties(0).total_memory / (1024**3)
94
- allocated_vram = torch.cuda.memory_allocated() / (1024**3)
95
- available_vram = total_vram - allocated_vram
96
- if available_vram < required_gb:
97
- print(f"WARNING: Low VRAM available ({available_vram:.2f} GB). Reduce total_duration or chunk_duration.")
98
- return available_vram >= required_gb
99
-
100
- # 4) GENRE PROMPT FUNCTIONS
101
- def set_red_hot_chili_peppers_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
102
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("strong rhythmic steps" if bpm > 120 else "groovy rhythmic flow")
103
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
104
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
105
- bass = f", {bass_style}" if bass_style != "none" else ", groovy basslines"
106
- guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else ", syncopated guitar riffs"
107
- return f"Instrumental funk rock{bass}{guitar}{drum}{synth}, Red Hot Chili Peppers-inspired vibe with dynamic energy and funky breakdowns, {rhythm} at {bpm} BPM."
108
-
109
- def set_nirvana_grunge_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
110
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("intense rhythmic steps" if bpm > 120 else "grungy rhythmic pulse")
111
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
112
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
113
- bass = f", {bass_style}" if bass_style != "none" else ", melodic basslines"
114
- guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else ", raw distorted guitar riffs"
115
- return f"Instrumental grunge{bass}{guitar}{drum}{synth}, Nirvana-inspired angst-filled sound with quiet-loud dynamics, {rhythm} at {bpm} BPM."
116
-
117
- def set_pearl_jam_grunge_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
118
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("soulful rhythmic steps" if bpm > 120 else "driving rhythmic flow")
119
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
120
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
121
- bass = f", {bass_style}" if bass_style != "none" else ", deep bass"
122
- guitar = f", {guitar_style} guitar leads" if guitar_style != "none" else ", soulful guitar leads"
123
- return f"Instrumental grunge{bass}{guitar}{drum}{synth}, Pearl Jam-inspired emotional intensity with soaring choruses, {rhythm} at {bpm} BPM."
124
-
125
- def set_soundgarden_grunge_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
126
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("heavy rhythmic steps" if bpm > 120 else "sludgy rhythmic groove")
127
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
128
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
129
- bass = f", {bass_style}" if bass_style != "none" else ""
130
- guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else ", heavy sludgy guitar riffs"
131
- return f"Instrumental grunge{bass}{guitar}{drum}{synth}, Soundgarden-inspired dark, psychedelic edge, {rhythm} at {bpm} BPM."
132
-
133
- def set_foo_fighters_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
 
 
 
 
 
 
 
 
 
 
134
  styles = ["anthemic", "gritty", "melodic", "fast-paced", "driving"]
135
- tempos = ["upbeat", "mid-tempo", "high-energy"]
136
- moods = ["energetic", "introspective", "rebellious", "uplifting"]
137
- style = random.choice(styles)
138
- tempo = random.choice(tempos)
139
- mood = random.choice(moods)
140
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("powerful rhythmic steps" if bpm > 120 else "catchy rhythmic groove")
141
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
142
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
143
- bass = f", {bass_style}" if bass_style != "none" else ""
144
- guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else f", {style} guitar riffs"
145
- return f"Instrumental alternative rock{bass}{guitar}{drum}{synth}, Foo Fighters-inspired {mood} vibe with powerful choruses, {rhythm} at {bpm} BPM."
146
-
147
- def set_smashing_pumpkins_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
148
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("dynamic rhythmic steps" if bpm > 120 else "dreamy rhythmic flow")
149
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
150
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
151
- bass = f", {bass_style}" if bass_style != "none" else ""
152
- guitar = f", {guitar_style} guitar textures" if guitar_style != "none" else ", dreamy guitar textures"
153
- return f"Instrumental alternative rock{bass}{guitar}{drum}{synth}, Smashing Pumpkins-inspired blend of melancholy and aggression, {rhythm} at {bpm} BPM."
154
-
155
- def set_radiohead_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
156
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("complex rhythmic steps" if bpm > 120 else "intricate rhythmic pulse")
157
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
158
- synth = f", {synthesizer} accents" if synthesizer != "none" else ", atmospheric synths"
159
- bass = f", {bass_style}" if bass_style != "none" else ""
160
- guitar = f", {guitar_style} guitar layers" if guitar_style != "none" else ", intricate guitar layers"
161
- return f"Instrumental experimental rock{bass}{guitar}{drum}{synth}, Radiohead-inspired blend of introspective and innovative soundscapes, {rhythm} at {bpm} BPM."
162
-
163
- def set_classic_rock_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
164
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("bluesy rhythmic steps" if bpm > 120 else "steady rhythmic groove")
165
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
166
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
167
- bass = f", {bass_style}" if bass_style != "none" else ", groovy bass"
168
- guitar = f", {guitar_style} electric guitars" if guitar_style != "none" else ", bluesy electric guitars"
169
- return f"Instrumental classic rock{bass}{guitar}{drum}{synth}, Led Zeppelin-inspired raw energy with dynamic solos, {rhythm} at {bpm} BPM."
170
-
171
- def set_alternative_rock_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
172
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("quirky rhythmic steps" if bpm > 120 else "energetic rhythmic flow")
173
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
174
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
175
- bass = f", {bass_style}" if bass_style != "none" else ", melodic basslines"
176
- guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else ", distorted guitar riffs"
177
- return f"Instrumental alternative rock{bass}{guitar}{drum}{synth}, Pixies-inspired quirky, energetic vibe, {rhythm} at {bpm} BPM."
178
-
179
- def set_post_punk_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
180
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("sharp rhythmic steps" if bpm > 120 else "moody rhythmic pulse")
181
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
182
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
183
- bass = f", {bass_style}" if bass_style != "none" else ", driving basslines"
184
- guitar = f", {guitar_style} guitars" if guitar_style != "none" else ", jangly guitars"
185
- return f"Instrumental post-punk{bass}{guitar}{drum}{synth}, Joy Division-inspired moody, atmospheric sound, {rhythm} at {bpm} BPM."
186
-
187
- def set_indie_rock_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
188
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("catchy rhythmic steps" if bpm > 120 else "jangly rhythmic flow")
189
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
190
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
191
- bass = f", {bass_style}" if bass_style != "none" else ""
192
- guitar = f", {guitar_style} guitars" if guitar_style != "none" else ", jangly guitars"
193
- return f"Instrumental indie rock{bass}{guitar}{drum}{synth}, Arctic Monkeys-inspired blend of catchy riffs, {rhythm} at {bpm} BPM."
194
-
195
- def set_funk_rock_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
196
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("aggressive rhythmic steps" if bpm > 120 else "funky rhythmic groove")
197
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
198
- synth = f", {synthesizer} accents" if synthesizer != "none" else ""
199
- bass = f", {bass_style}" if bass_style != "none" else ", slap bass"
200
- guitar = f", {guitar_style} guitar chords" if guitar_style != "none" else ", funky guitar chords"
201
- return f"Instrumental funk rock{bass}{guitar}{drum}{synth}, Rage Against the Machine-inspired mix of groove and aggression, {rhythm} at {bpm} BPM."
202
-
203
- def set_detroit_techno_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
204
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("pulsing rhythmic steps" if bpm > 120 else "deep rhythmic groove")
205
- drum = f", {drum_beat} drums" if drum_beat != "none" else ", crisp hi-hats"
206
- synth = f", {synthesizer} accents" if synthesizer != "none" else ", deep pulsing synths"
207
- bass = f", {bass_style}" if bass_style != "none" else ", driving basslines"
208
- guitar = f", {guitar_style} guitars" if guitar_style != "none" else ""
209
- return f"Instrumental Detroit techno{bass}{guitar}{drum}{synth}, Juan Atkins-inspired rhythmic groove, {rhythm} at {bpm} BPM."
210
-
211
- def set_deep_house_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
212
- rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("soulful rhythmic steps" if bpm > 120 else "laid-back rhythmic flow")
213
- drum = f", {drum_beat} drums" if drum_beat != "none" else ""
214
- synth = f", {synthesizer} accents" if synthesizer != "none" else ", warm analog synth chords"
215
- bass = f", {bass_style}" if bass_style != "none" else ", deep basslines"
216
- guitar = f", {guitar_style} guitars" if guitar_style != "none" else ""
217
- return f"Instrumental deep house{bass}{guitar}{drum}{synth}, Larry Heard-inspired laid-back groove, {rhythm} at {bpm} BPM."
218
-
219
- # 5) AUDIO PROCESSING FUNCTIONS
220
- def apply_eq(segment):
221
- segment = segment.low_pass_filter(8000)
222
- segment = segment.high_pass_filter(80)
223
- return segment
224
-
225
- def apply_fade(segment, fade_in_duration=1000, fade_out_duration=1000):
226
- segment = segment.fade_in(fade_in_duration)
227
- segment = segment.fade_out(fade_out_duration)
228
- return segment
229
-
230
- # 6) GENERATION & I/O FUNCTIONS
231
- def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p: float, temperature: float, total_duration: int, chunk_duration: int, crossfade_duration: int, bpm: int, drum_beat: str, synthesizer: str, rhythmic_steps: str, bass_style: str, guitar_style: str):
232
- global musicgen_model
233
- if not instrumental_prompt.strip():
234
- return None, "⚠️ Please enter a valid instrumental prompt!"
235
- try:
236
- start_time = time.time()
237
- total_duration = total_duration # Validated by radio button (30, 60, 90, 120)
238
- chunk_duration = min(max(chunk_duration, 5), 15)
239
- num_chunks = max(1, total_duration // chunk_duration)
240
- chunk_duration = total_duration / num_chunks
241
- overlap_duration = min(1.0, crossfade_duration / 1000.0)
242
- generation_duration = chunk_duration + overlap_duration
243
- sample_rate = musicgen_model.sample_rate
244
- audio_segments = []
245
-
246
- if not check_vram_availability(required_gb=3.5):
247
- return None, "⚠️ Insufficient VRAM for generation. Reduce total_duration or chunk_duration."
248
-
249
- print("Generating audio...")
250
- seed = 42
251
- torch.manual_seed(seed)
252
- np.random.seed(seed)
253
-
254
- for i in range(num_chunks):
255
- chunk_prompt = instrumental_prompt
256
- print(f"Generating chunk {i+1}/{num_chunks} on {device} (prompt: {chunk_prompt})...")
257
- musicgen_model.set_generation_params(
258
- duration=generation_duration,
259
- use_sampling=True,
260
- top_k=top_k,
261
- top_p=top_p,
262
- temperature=temperature,
263
- cfg_coef=cfg_scale
264
- )
265
-
266
- print_resource_usage(f"Before Chunk {i+1} Generation")
267
-
268
- with torch.no_grad():
269
- with autocast():
270
- audio_chunk = musicgen_model.generate([chunk_prompt], progress=True)[0]
271
-
272
- audio_chunk = audio_chunk.cpu().to(dtype=torch.float32)
273
- if audio_chunk.dim() == 1:
274
- audio_chunk = torch.stack([audio_chunk, audio_chunk], dim=0)
275
- elif audio_chunk.dim() == 2 and audio_chunk.shape[0] == 1:
276
- audio_chunk = torch.cat([audio_chunk, audio_chunk], dim=0)
277
- elif audio_chunk.dim() == 2 and audio_chunk.shape[0] != 2:
278
- audio_chunk = audio_chunk[:1, :]
279
- audio_chunk = torch.cat([audio_chunk, audio_chunk], dim=0)
280
- elif audio_chunk.dim() > 2:
281
- audio_chunk = audio_chunk.view(2, -1)
282
-
283
- if audio_chunk.shape[0] != 2:
284
- raise ValueError(f"Expected stereo audio with shape (2, samples), got shape {audio_chunk.shape}")
285
-
286
- with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_wav:
287
- temp_wav_path = temp_wav.name
288
- torchaudio.save(temp_wav_path, audio_chunk, sample_rate, bits_per_sample=24)
289
- segment = AudioSegment.from_wav(temp_wav_path)
290
- os.unlink(temp_wav_path)
291
- audio_segments.append(segment)
292
-
293
- if device == "cuda":
294
- torch.cuda.empty_cache()
295
- gc.collect()
296
- torch.cuda.ipc_collect()
297
- torch.cuda.synchronize()
298
- time.sleep(0.5)
299
- print_resource_usage(f"After Chunk {i+1} Generation")
300
-
301
- print("Combining audio chunks...")
302
- final_segment = audio_segments[0]
303
- for i in range(1, len(audio_segments)):
304
- next_segment = audio_segments[i]
305
- next_segment = next_segment + 1
306
- final_segment = final_segment.append(next_segment, crossfade=crossfade_duration)
307
-
308
- final_segment = final_segment[:total_duration * 1000]
309
-
310
- print("Post-processing final track...")
311
- final_segment = apply_eq(final_segment)
312
- final_segment = final_segment.normalize(headroom=-9.0)
313
- final_segment = apply_fade(final_segment)
314
-
315
- mp3_path = "output_cleaned.mp3"
316
- final_segment.export(
317
- mp3_path,
318
- format="mp3",
319
- bitrate="128k",
320
- tags={"title": "GhostAI Instrumental", "artist": "GhostAI"}
321
- )
322
- print(f"Saved final audio to {mp3_path}")
323
 
324
- print_resource_usage("After Final Generation")
325
- print(f"Total Generation Time: {time.time() - start_time:.2f} seconds")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
 
327
- return mp3_path, "βœ… Done! Generated instrumental audio."
328
- except Exception as e:
329
- return None, f"❌ Generation failed: {e}"
330
- finally:
331
  if device == "cuda":
332
  torch.cuda.empty_cache()
333
  gc.collect()
334
  torch.cuda.ipc_collect()
335
  torch.cuda.synchronize()
336
 
337
- # Function to clear inputs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  def clear_inputs():
339
- return "", 3.0, 250, 0.9, 1.0, 30, 10, 1000, 120, "none", "none", "none", "none", "none"
 
340
 
341
- # 7) CUSTOM CSS
 
 
342
  css = """
343
- body {
344
- background: linear-gradient(135deg, #0A0A0A 0%, #1C2526 100%);
345
- color: #E0E0E0;
346
- font-family: 'Orbitron', sans-serif;
347
- }
348
- .header-container {
349
- text-align: center;
350
- padding: 10px 20px;
351
- background: rgba(0, 0, 0, 0.9);
352
- border-bottom: 1px solid #00FF9F;
353
- }
354
- #ghost-logo {
355
- font-size: 40px;
356
- animation: glitch-ghost 1.5s infinite;
357
- }
358
- h1 {
359
- color: #A100FF;
360
- font-size: 24px;
361
- animation: glitch-text 2s infinite;
362
- }
363
- p {
364
- color: #E0E0E0;
365
- font-size: 12px;
366
- }
367
- .input-container, .settings-container, .output-container {
368
- max-width: 1200px;
369
- margin: 20px auto;
370
- padding: 20px;
371
- background: rgba(28, 37, 38, 0.8);
372
- border-radius: 10px;
373
- }
374
- .textbox {
375
- background: #1A1A1A;
376
- border: 1px solid #A100FF;
377
- color: #E0E0E0;
378
- }
379
- .genre-buttons {
380
- display: flex;
381
- justify-content: center;
382
- flex-wrap: wrap;
383
- gap: 15px;
384
- }
385
- .genre-btn, button {
386
- background: linear-gradient(45deg, #A100FF, #00FF9F);
387
- border: none;
388
- color: #0A0A0A;
389
- padding: 10px 20px;
390
- border-radius: 5px;
391
- }
392
- .gradio-container {
393
- padding: 20px;
394
- }
395
- .group-container {
396
- margin-bottom: 20px;
397
- padding: 15px;
398
- border: 1px solid #00FF9F;
399
- border-radius: 8px;
400
- }
401
- @keyframes glitch-ghost {
402
- 0% { transform: translate(0, 0); opacity: 1; }
403
- 20% { transform: translate(-5px, 2px); opacity: 0.8; }
404
- 100% { transform: translate(0, 0); opacity: 1; }
405
- }
406
- @keyframes glitch-text {
407
- 0% { transform: translate(0, 0); }
408
- 20% { transform: translate(-2px, 1px); }
409
- 100% { transform: translate(0, 0); }
410
- }
411
- @font-face {
412
- font-family: 'Orbitron';
413
- src: url('https://fonts.gstatic.com/s/orbitron/v29/yMJRMIlzdpvBhQQL_Qq7dy0.woff2') format('woff2');
414
- }
415
  """
416
 
417
- # 8) BUILD WITH BLOCKS
 
 
418
  with gr.Blocks(css=css) as demo:
419
  gr.Markdown("""
420
- <div class="header-container">
421
- <div id="ghost-logo">πŸ‘»</div>
422
- <h1>GhostAI Music Generator 🎹</h1>
423
- <p>Summon the Sound of the Unknown</p>
424
- </div>
425
  """)
426
-
 
427
  with gr.Column(elem_classes="input-container"):
428
  gr.Markdown("### 🎸 Prompt Settings")
429
- instrumental_prompt = gr.Textbox(
430
- label="Instrumental Prompt ✍️",
431
- placeholder="Click a genre button or type your own instrumental prompt",
432
- lines=4,
433
- elem_classes="textbox"
434
- )
435
  with gr.Row(elem_classes="genre-buttons"):
436
- rhcp_btn = gr.Button("Red Hot Chili Peppers 🌢️", elem_classes="genre-btn")
437
- nirvana_btn = gr.Button("Nirvana Grunge 🎸", elem_classes="genre-btn")
438
- pearl_jam_btn = gr.Button("Pearl Jam Grunge πŸ¦ͺ", elem_classes="genre-btn")
439
- soundgarden_btn = gr.Button("Soundgarden Grunge πŸŒ‘", elem_classes="genre-btn")
440
- foo_fighters_btn = gr.Button("Foo Fighters 🀘", elem_classes="genre-btn")
441
- smashing_pumpkins_btn = gr.Button("Smashing Pumpkins πŸŽƒ", elem_classes="genre-btn")
442
- radiohead_btn = gr.Button("Radiohead 🧠", elem_classes="genre-btn")
443
- classic_rock_btn = gr.Button("Classic Rock 🎸", elem_classes="genre-btn")
444
- alternative_rock_btn = gr.Button("Alternative Rock 🎡", elem_classes="genre-btn")
445
- post_punk_btn = gr.Button("Post-Punk πŸ–€", elem_classes="genre-btn")
446
- indie_rock_btn = gr.Button("Indie Rock 🎀", elem_classes="genre-btn")
447
- funk_rock_btn = gr.Button("Funk Rock πŸ•Ί", elem_classes="genre-btn")
448
- detroit_techno_btn = gr.Button("Detroit Techno πŸŽ›οΈ", elem_classes="genre-btn")
449
- deep_house_btn = gr.Button("Deep House 🏠", elem_classes="genre-btn")
450
-
 
 
 
 
 
 
 
 
 
 
451
  with gr.Column(elem_classes="settings-container"):
452
  gr.Markdown("### βš™οΈ API Settings")
453
  with gr.Group(elem_classes="group-container"):
454
- cfg_scale = gr.Slider(
455
- label="CFG Scale 🎯",
456
- minimum=1.0,
457
- maximum=10.0,
458
- value=3.0,
459
- step=0.1,
460
- info="Controls how closely the music follows the prompt."
461
- )
462
- top_k = gr.Slider(
463
- label="Top-K Sampling πŸ”’",
464
- minimum=10,
465
- maximum=500,
466
- value=250,
467
- step=10,
468
- info="Limits sampling to the top k most likely tokens."
469
- )
470
- top_p = gr.Slider(
471
- label="Top-P Sampling 🎰",
472
- minimum=0.0,
473
- maximum=1.0,
474
- value=0.9,
475
- step=0.05,
476
- info="Keeps tokens with cumulative probability above p."
477
- )
478
- temperature = gr.Slider(
479
- label="Temperature πŸ”₯",
480
- minimum=0.1,
481
- maximum=2.0,
482
- value=1.0,
483
- step=0.1,
484
- info="Controls randomness; higher values increase diversity."
485
- )
486
- total_duration = gr.Radio(
487
- label="Song Length ⏳ (seconds)",
488
- choices=[30, 60, 90, 120],
489
- value=30,
490
- info="Select the total duration of the track."
491
- )
492
- chunk_duration = gr.Slider(
493
- label="Chunk Duration ⏱️ (seconds)",
494
- minimum=5,
495
- maximum=15,
496
- value=10,
497
- step=1,
498
- info="Duration of each chunk to render (5 to 15 seconds)."
499
- )
500
- crossfade_duration = gr.Slider(
501
- label="Crossfade Duration 🎢 (ms)",
502
- minimum=100,
503
- maximum=2000,
504
- value=1000,
505
- step=100,
506
- info="Crossfade duration between chunks."
507
- )
508
 
509
  gr.Markdown("### 🎡 Musical Controls")
510
  with gr.Group(elem_classes="group-container"):
511
- bpm = gr.Slider(
512
- label="Tempo 🎡 (BPM)",
513
- minimum=60,
514
- maximum=180,
515
- value=120,
516
- step=1,
517
- info="Beats per minute to set the track's tempo."
518
- )
519
- drum_beat = gr.Dropdown(
520
- label="Drum Beat πŸ₯",
521
- choices=["none", "standard rock", "funk groove", "techno kick", "jazz swing"],
522
- value="none",
523
- info="Select a drum beat style to influence the rhythm."
524
- )
525
- synthesizer = gr.Dropdown(
526
- label="Synthesizer 🎹",
527
- choices=["none", "analog synth", "digital pad", "arpeggiated synth"],
528
- value="none",
529
- info="Select a synthesizer style for electronic accents."
530
- )
531
- rhythmic_steps = gr.Dropdown(
532
- label="Rhythmic Steps πŸ‘£",
533
- choices=["none", "syncopated steps", "steady steps", "complex steps"],
534
- value="none",
535
- info="Select a rhythmic step style to enhance the beat."
536
- )
537
- bass_style = gr.Dropdown(
538
- label="Bass Style 🎸",
539
- choices=["none", "slap bass", "deep bass", "melodic bass"],
540
- value="none",
541
- info="Select a bass style to shape the low end."
542
- )
543
- guitar_style = gr.Dropdown(
544
- label="Guitar Style 🎸",
545
- choices=["none", "distorted", "clean", "jangle"],
546
- value="none",
547
- info="Select a guitar style to define the riffs."
548
- )
549
 
550
  with gr.Row(elem_classes="action-buttons"):
551
  gen_btn = gr.Button("Generate Music πŸš€")
552
  clr_btn = gr.Button("Clear Inputs 🧹")
553
-
 
554
  with gr.Column(elem_classes="output-container"):
555
  gr.Markdown("### 🎧 Output")
556
- out_audio = gr.Audio(label="Generated Instrumental Track 🎡", type="filepath")
557
- status = gr.Textbox(label="Status πŸ“’", interactive=False)
558
-
559
- rhcp_btn.click(set_red_hot_chili_peppers_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
560
- nirvana_btn.click(set_nirvana_grunge_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
561
- pearl_jam_btn.click(set_pearl_jam_grunge_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
562
- soundgarden_btn.click(set_soundgarden_grunge_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
563
- foo_fighters_btn.click(set_foo_fighters_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
564
- smashing_pumpkins_btn.click(set_smashing_pumpkins_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
565
- radiohead_btn.click(set_radiohead_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
566
- classic_rock_btn.click(set_classic_rock_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
567
- alternative_rock_btn.click(set_alternative_rock_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
568
- post_punk_btn.click(set_post_punk_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
569
- indie_rock_btn.click(set_indie_rock_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
570
- funk_rock_btn.click(set_funk_rock_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
571
- detroit_techno_btn.click(set_detroit_techno_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
572
- deep_house_btn.click(set_deep_house_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
573
  gen_btn.click(
574
  generate_music,
575
- inputs=[instrumental_prompt, cfg_scale, top_k, top_p, temperature, total_duration, chunk_duration, crossfade_duration, bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style],
 
 
576
  outputs=[out_audio, status]
577
  )
578
  clr_btn.click(
579
  clear_inputs,
580
  inputs=None,
581
- outputs=[instrumental_prompt, cfg_scale, top_k, top_p, temperature, total_duration, chunk_duration, crossfade_duration, bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style]
 
 
582
  )
583
 
584
- # 9) TURN OFF OPENAPI/DOCS
585
- app = demo.launch(
586
- share=False,
587
- inbrowser=False,
588
- show_error=True
589
- )
590
  try:
591
  fastapi_app = demo._server.app
592
- fastapi_app.docs_url = None
593
- fastapi_app.redoc_url = None
594
  fastapi_app.openapi_url = None
595
  except Exception:
596
- pass
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ GhostAI Music Generator
5
+ Full script with compatibility fixes for environments running
6
+ PyTorch < 2.3 (adds torch.get_default_device shim).
7
+
8
+ Last updated: 2025-05-29
9
+ """
10
+
11
  import os
 
 
 
 
12
  import sys
 
13
  import gc
14
+ import time
15
+ import random
16
+ import warnings
17
+ import tempfile
18
+ import psutil
19
+ import numpy as np
20
+ import torch
21
+ import torchaudio
22
  import gradio as gr
23
  from pydub import AudioSegment
 
24
  from torch.cuda.amp import autocast
25
+ from audiocraft.models import MusicGen
 
26
  from huggingface_hub import login
 
27
 
28
+ # ----------------------------------------------------------------------
29
+ # PYTORCH COMPATIBILITY SHIM (for versions < 2.3)
30
+ # ----------------------------------------------------------------------
31
+ if not hasattr(torch, "get_default_device"):
32
+ def _get_default_device():
33
+ return torch.device("cuda" if torch.cuda.is_available() else "cpu")
34
+ torch.get_default_device = _get_default_device
35
+
36
+ # ----------------------------------------------------------------------
37
+ # WARNING SUPPRESSION & ENV TUNING
38
+ # ----------------------------------------------------------------------
39
  warnings.filterwarnings("ignore")
 
 
40
  os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
41
 
42
+ # ----------------------------------------------------------------------
43
+ # HUGGING FACE AUTH
44
+ # ----------------------------------------------------------------------
45
  hf_token = os.getenv("HF_TOKEN")
46
  if not hf_token:
47
+ print("ERROR: HF_TOKEN environment variable not set. Please set it.")
48
  sys.exit(1)
49
+
50
  try:
51
  login(hf_token)
52
  except Exception as e:
53
  print(f"ERROR: Failed to authenticate with Hugging Face: {e}")
54
  sys.exit(1)
55
 
56
+ # ----------------------------------------------------------------------
57
+ # VERSION CHECKS
58
+ # ----------------------------------------------------------------------
59
  if np.__version__ != "1.23.5":
60
+ print(f"WARNING: NumPy version {np.__version__} detected (expected 1.23.5).")
61
  if not torch.__version__.startswith("2.3.1"):
62
+ print(f"WARNING: PyTorch version {torch.__version__} detected (expected 2.3.1).")
63
 
64
+ # ----------------------------------------------------------------------
65
+ # DEVICE SETUP
66
+ # ----------------------------------------------------------------------
67
+ print("Debugging GPU and CUDA setup…")
68
  print(f"PyTorch CUDA available: {torch.cuda.is_available()}")
69
  if torch.cuda.is_available():
70
+ print(f"CUDA device count : {torch.cuda.device_count()}")
71
+ print(f"CUDA device name : {torch.cuda.get_device_name(0)}")
72
+ print(f"CUDA version : {torch.version.cuda}")
 
73
  else:
74
+ print("CUDA unavailable; falling back to CPU (performance will suffer).")
 
 
 
75
 
76
  device = "cuda" if torch.cuda.is_available() else "cpu"
 
 
77
 
78
+ # Pre-run memory cleanup (GPU)
79
  if device == "cuda":
80
  torch.cuda.empty_cache()
81
  gc.collect()
82
  torch.cuda.ipc_collect()
83
  torch.cuda.synchronize()
84
 
85
+ # ----------------------------------------------------------------------
86
+ # LOAD MUSICGEN
87
+ # ----------------------------------------------------------------------
88
  try:
89
+ print("Loading MusicGen medium model…")
90
  musicgen_model = MusicGen.get_pretrained("facebook/musicgen-medium", device=device)
91
+ musicgen_model.set_generation_params(duration=10, two_step_cfg=False)
 
 
 
92
  except Exception as e:
93
  print(f"ERROR: Failed to load MusicGen model: {e}")
94
+ print("Check HF access and PyTorch version compatibility.")
95
  sys.exit(1)
96
 
97
+ # ----------------------------------------------------------------------
98
+ # HELPER: RESOURCE MONITOR
99
+ # ----------------------------------------------------------------------
100
  def print_resource_usage(stage: str):
101
  print(f"--- {stage} ---")
102
  if device == "cuda":
103
  print(f"GPU Memory Allocated: {torch.cuda.memory_allocated() / (1024**3):.2f} GB")
104
+ print(f"GPU Memory Reserved : {torch.cuda.memory_reserved() / (1024**3):.2f} GB")
105
+ print(f"CPU Memory Used : {psutil.virtual_memory().percent}%")
106
+ print("--------------------")
107
 
108
+ def check_vram(required_gb=3.5):
 
109
  if device != "cuda":
 
110
  return True
111
+ total = torch.cuda.get_device_properties(0).total_memory / (1024**3)
112
+ used = torch.cuda.memory_allocated() / (1024**3)
113
+ avail = total - used
114
+ if avail < required_gb:
115
+ print(f"WARNING: Only {avail:.2f} GB VRAM free (need β‰₯ {required_gb} GB).")
116
+ return avail >= required_gb
117
+
118
+ # ----------------------------------------------------------------------
119
+ # PROMPT BUILDERS (UNCHANGED)
120
+ # ----------------------------------------------------------------------
121
+ def _prompt(base, bpm, drum, synth, steps, bass, guitar, default_bass, default_gtr, vibe):
122
+ rhythm = f" with {steps}" if steps != "none" else vibe.format(bpm=bpm)
123
+ drum = f", {drum} drums" if drum != "none" else ""
124
+ synth = f", {synth} accents" if synth != "none" else ""
125
+ bass = f", {bass}" if bass != "none" else default_bass
126
+ guitar = f", {guitar} guitar riffs" if guitar != "none" else default_gtr
127
+ return f"{base}{bass}{guitar}{drum}{synth}{rhythm} at {bpm} BPM."
128
+
129
+ def set_red_hot_chili_peppers_prompt(bpm, drum, synth, steps, bass, guitar):
130
+ return _prompt(
131
+ "Instrumental funk rock",
132
+ bpm, drum, synth, steps, bass, guitar,
133
+ ", groovy basslines", ", syncopated guitar riffs",
134
+ "{bpm} BPM funky flow" if bpm > 120 else "groovy rhythmic flow"
135
+ )
136
+
137
+ def set_nirvana_grunge_prompt(bpm, drum, synth, steps, bass, guitar):
138
+ return _prompt(
139
+ "Instrumental grunge",
140
+ bpm, drum, synth, steps, bass, guitar,
141
+ ", melodic basslines", ", raw distorted guitar riffs",
142
+ "{bpm} BPM grungy pulse" if bpm > 120 else "grungy rhythmic pulse"
143
+ )
144
+
145
+ def set_pearl_jam_grunge_prompt(bpm, drum, synth, steps, bass, guitar):
146
+ return _prompt(
147
+ "Instrumental grunge",
148
+ bpm, drum, synth, steps, bass, guitar,
149
+ ", deep bass", ", soulful guitar leads",
150
+ "{bpm} BPM driving flow" if bpm > 120 else "driving rhythmic flow"
151
+ )
152
+
153
+ def set_soundgarden_grunge_prompt(bpm, drum, synth, steps, bass, guitar):
154
+ return _prompt(
155
+ "Instrumental grunge",
156
+ bpm, drum, synth, steps, bass, guitar,
157
+ "", ", heavy sludgy guitar riffs",
158
+ "{bpm} BPM heavy groove" if bpm > 120 else "sludgy rhythmic groove"
159
+ )
160
+
161
+ def set_foo_fighters_prompt(bpm, drum, synth, steps, bass, guitar):
162
  styles = ["anthemic", "gritty", "melodic", "fast-paced", "driving"]
163
+ moods = ["energetic", "introspective", "rebellious", "uplifting"]
164
+ style = random.choice(styles)
165
+ mood = random.choice(moods)
166
+ return _prompt(
167
+ "Instrumental alternative rock",
168
+ bpm, drum, synth, steps, bass, guitar,
169
+ "", f", {style} guitar riffs",
170
+ "{bpm} BPM powerful groove" if bpm > 120 else "catchy rhythmic groove"
171
+ ) + f", Foo Fighters-inspired {mood} vibe"
172
+
173
+ def set_smashing_pumpkins_prompt(bpm, drum, synth, steps, bass, guitar):
174
+ return _prompt(
175
+ "Instrumental alternative rock",
176
+ bpm, drum, synth, steps, bass, guitar,
177
+ "", ", dreamy guitar textures",
178
+ "{bpm} BPM dynamic flow" if bpm > 120 else "dreamy rhythmic flow"
179
+ )
180
+
181
+ def set_radiohead_prompt(bpm, drum, synth, steps, bass, guitar):
182
+ return _prompt(
183
+ "Instrumental experimental rock",
184
+ bpm, drum, synth, steps, bass, guitar,
185
+ "", ", intricate guitar layers",
186
+ "{bpm} BPM intricate pulse" if bpm > 120 else "intricate rhythmic pulse"
187
+ )
188
+
189
+ def set_classic_rock_prompt(bpm, drum, synth, steps, bass, guitar):
190
+ return _prompt(
191
+ "Instrumental classic rock",
192
+ bpm, drum, synth, steps, bass, guitar,
193
+ ", groovy bass", ", bluesy electric guitars",
194
+ "{bpm} BPM bluesy steps" if bpm > 120 else "steady rhythmic groove"
195
+ )
196
+
197
+ def set_alternative_rock_prompt(bpm, drum, synth, steps, bass, guitar):
198
+ return _prompt(
199
+ "Instrumental alternative rock",
200
+ bpm, drum, synth, steps, bass, guitar,
201
+ ", melodic basslines", ", distorted guitar riffs",
202
+ "{bpm} BPM quirky steps" if bpm > 120 else "energetic rhythmic flow"
203
+ )
204
+
205
+ def set_post_punk_prompt(bpm, drum, synth, steps, bass, guitar):
206
+ return _prompt(
207
+ "Instrumental post-punk",
208
+ bpm, drum, synth, steps, bass, guitar,
209
+ ", driving basslines", ", jangly guitars",
210
+ "{bpm} BPM sharp steps" if bpm > 120 else "moody rhythmic pulse"
211
+ )
212
+
213
+ def set_indie_rock_prompt(bpm, drum, synth, steps, bass, guitar):
214
+ return _prompt(
215
+ "Instrumental indie rock",
216
+ bpm, drum, synth, steps, bass, guitar,
217
+ "", ", jangly guitars",
218
+ "{bpm} BPM catchy steps" if bpm > 120 else "jangly rhythmic flow"
219
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
 
221
+ def set_funk_rock_prompt(bpm, drum, synth, steps, bass, guitar):
222
+ return _prompt(
223
+ "Instrumental funk rock",
224
+ bpm, drum, synth, steps, bass, guitar,
225
+ ", slap bass", ", funky guitar chords",
226
+ "{bpm} BPM aggressive steps" if bpm > 120 else "funky rhythmic groove"
227
+ )
228
+
229
+ def set_detroit_techno_prompt(bpm, drum, synth, steps, bass, guitar):
230
+ return _prompt(
231
+ "Instrumental Detroit techno",
232
+ bpm, drum, synth, steps, bass, guitar,
233
+ ", driving basslines", "",
234
+ "{bpm} BPM pulsing steps" if bpm > 120 else "deep rhythmic groove"
235
+ )
236
+
237
+ def set_deep_house_prompt(bpm, drum, synth, steps, bass, guitar):
238
+ return _prompt(
239
+ "Instrumental deep house",
240
+ bpm, drum, synth, steps, bass, guitar,
241
+ ", deep basslines", "",
242
+ "{bpm} BPM soulful steps" if bpm > 120 else "laid-back rhythmic flow"
243
+ )
244
+
245
+ # ----------------------------------------------------------------------
246
+ # AUDIO POST-PROCESSING
247
+ # ----------------------------------------------------------------------
248
+ def apply_eq(seg: AudioSegment):
249
+ return seg.low_pass_filter(8000).high_pass_filter(80)
250
+
251
+ def apply_fade(seg: AudioSegment, fin=1000, fout=1000):
252
+ return seg.fade_in(fin).fade_out(fout)
253
+
254
+ # ----------------------------------------------------------------------
255
+ # CORE GENERATION
256
+ # ----------------------------------------------------------------------
257
+ def generate_music(prompt, cfg, k, p, temp,
258
+ total_dur, chunk_dur, crossfade,
259
+ bpm, drum, synth, steps, bass, guitar):
260
+
261
+ if not prompt.strip():
262
+ return None, "⚠️ Please enter a prompt."
263
+
264
+ if not check_vram(3.5):
265
+ return None, "⚠️ Insufficient VRAM. Lower duration."
266
+
267
+ total_dur = int(total_dur)
268
+ chunk_dur = int(max(5, min(chunk_dur, 15)))
269
+ num_chunks = max(1, total_dur // chunk_dur)
270
+ chunk_dur = total_dur / num_chunks
271
+ overlap = min(1.0, crossfade / 1000.0)
272
+ render_len = chunk_dur + overlap
273
+ sr = musicgen_model.sample_rate
274
+ segments = []
275
+
276
+ torch.manual_seed(42)
277
+ np.random.seed(42)
278
+
279
+ start = time.time()
280
+ for i in range(num_chunks):
281
+ print_resource_usage(f"Before chunk {i+1}")
282
+ musicgen_model.set_generation_params(
283
+ duration=render_len,
284
+ use_sampling=True,
285
+ top_k=k, top_p=p,
286
+ temperature=temp,
287
+ cfg_coef=cfg
288
+ )
289
+ with torch.no_grad(), autocast():
290
+ chunk = musicgen_model.generate([prompt], progress=False)[0]
291
+
292
+ chunk = chunk.cpu().float()
293
+ if chunk.dim() == 1:
294
+ chunk = torch.stack([chunk, chunk])
295
+ elif chunk.shape[0] == 1:
296
+ chunk = torch.cat([chunk, chunk], dim=0)
297
+ elif chunk.shape[0] != 2:
298
+ chunk = chunk[:1]
299
+ chunk = torch.cat([chunk, chunk], dim=0)
300
+
301
+ with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
302
+ torchaudio.save(tmp.name, chunk, sr, bits_per_sample=24)
303
+ seg = AudioSegment.from_wav(tmp.name)
304
+ os.unlink(tmp.name)
305
+ segments.append(seg)
306
 
 
 
 
 
307
  if device == "cuda":
308
  torch.cuda.empty_cache()
309
  gc.collect()
310
  torch.cuda.ipc_collect()
311
  torch.cuda.synchronize()
312
 
313
+ print_resource_usage(f"After chunk {i+1}")
314
+
315
+ final = segments[0]
316
+ for seg in segments[1:]:
317
+ final = final.append(seg + 1, crossfade=crossfade)
318
+ final = final[:total_dur * 1000]
319
+ final = apply_fade(apply_eq(final).normalize(headroom=-9.0))
320
+
321
+ out_path = "output_cleaned.mp3"
322
+ final.export(out_path, format="mp3", bitrate="128k",
323
+ tags={"title": "GhostAI Instrumental", "artist": "GhostAI"})
324
+ print_resource_usage("After final")
325
+ print(f"Total time: {time.time() - start:.2f}s")
326
+ return out_path, "βœ… Done!"
327
+
328
+ # ----------------------------------------------------------------------
329
+ # CLEAR INPUTS
330
+ # ----------------------------------------------------------------------
331
  def clear_inputs():
332
+ return ("", 3.0, 250, 0.9, 1.0, 30, 10, 1000,
333
+ 120, "none", "none", "none", "none", "none")
334
 
335
+ # ----------------------------------------------------------------------
336
+ # CSS
337
+ # ----------------------------------------------------------------------
338
  css = """
339
+ body{background:linear-gradient(135deg,#0A0A0A 0%,#1C2526 100%);color:#E0E0E0;font-family:'Orbitron',sans-serif}
340
+ .header-container{text-align:center;padding:10px 20px;background:rgba(0,0,0,.9);border-bottom:1px solid #00FF9F}
341
+ #ghost-logo{font-size:40px;animation:glitch-ghost 1.5s infinite}
342
+ h1{color:#A100FF;font-size:24px;animation:glitch-text 2s infinite}
343
+ p{color:#E0E0E0;font-size:12px}
344
+ .input-container,.settings-container,.output-container{max-width:1200px;margin:20px auto;padding:20px;background:rgba(28,37,38,.8);border-radius:10px}
345
+ .textbox{background:#1A1A1A;border:1px solid #A100FF;color:#E0E0E0}
346
+ .genre-buttons{display:flex;justify-content:center;flex-wrap:wrap;gap:15px}
347
+ .genre-btn,button{background:linear-gradient(45deg,#A100FF,#00FF9F);border:none;color:#0A0A0A;padding:10px 20px;border-radius:5px}
348
+ .gradio-container{padding:20px}
349
+ .group-container{margin-bottom:20px;padding:15px;border:1px solid #00FF9F;border-radius:8px}
350
+ @keyframes glitch-ghost{0%{transform:translate(0,0);opacity:1}20%{transform:translate(-5px,2px);opacity:.8}100%{transform:translate(0,0);opacity:1}}
351
+ @keyframes glitch-text{0%{transform:translate(0,0)}20%{transform:translate(-2px,1px)}100%{transform:translate(0,0)}}
352
+ @font-face{font-family:'Orbitron';src:url('https://fonts.gstatic.com/s/orbitron/v29/yMJRMIlzdpvBhQQL_Qq7dy0.woff2') format('woff2')}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
  """
354
 
355
+ # ----------------------------------------------------------------------
356
+ # GRADIO UI
357
+ # ----------------------------------------------------------------------
358
  with gr.Blocks(css=css) as demo:
359
  gr.Markdown("""
360
+ <div class="header-container">
361
+ <div id="ghost-logo">πŸ‘»</div>
362
+ <h1>GhostAI Music Generator 🎹</h1>
363
+ <p>Summon the Sound of the Unknown</p>
364
+ </div>
365
  """)
366
+
367
+ # INPUT
368
  with gr.Column(elem_classes="input-container"):
369
  gr.Markdown("### 🎸 Prompt Settings")
370
+ prompt_box = gr.Textbox(label="Instrumental Prompt ✍️",
371
+ placeholder="Click a genre button or type your own prompt",
372
+ lines=4, elem_classes="textbox")
 
 
 
373
  with gr.Row(elem_classes="genre-buttons"):
374
+ buttons = {
375
+ "Red Hot Chili Peppers 🌢️" : set_red_hot_chili_peppers_prompt,
376
+ "Nirvana Grunge 🎸" : set_nirvana_grunge_prompt,
377
+ "Pearl Jam Grunge πŸ¦ͺ" : set_pearl_jam_grunge_prompt,
378
+ "Soundgarden Grunge πŸŒ‘" : set_soundgarden_grunge_prompt,
379
+ "Foo Fighters 🀘" : set_foo_fighters_prompt,
380
+ "Smashing Pumpkins πŸŽƒ" : set_smashing_pumpkins_prompt,
381
+ "Radiohead 🧠" : set_radiohead_prompt,
382
+ "Classic Rock 🎸" : set_classic_rock_prompt,
383
+ "Alternative Rock 🎡" : set_alternative_rock_prompt,
384
+ "Post-Punk πŸ–€" : set_post_punk_prompt,
385
+ "Indie Rock 🎀" : set_indie_rock_prompt,
386
+ "Funk Rock πŸ•Ί" : set_funk_rock_prompt,
387
+ "Detroit Techno πŸŽ›οΈ" : set_detroit_techno_prompt,
388
+ "Deep House 🏠" : set_deep_house_prompt
389
+ }
390
+ for label, fn in buttons.items():
391
+ gr.Button(label, elem_classes="genre-btn").click(
392
+ fn,
393
+ inputs=[gr.State("bpm"), gr.State("drum"), gr.State("synth"),
394
+ gr.State("steps"), gr.State("bass"), gr.State("guitar")],
395
+ outputs=prompt_box
396
+ )
397
+
398
+ # SETTINGS
399
  with gr.Column(elem_classes="settings-container"):
400
  gr.Markdown("### βš™οΈ API Settings")
401
  with gr.Group(elem_classes="group-container"):
402
+ cfg_scale = gr.Slider(label="CFG Scale 🎯", minimum=1, maximum=10, value=3, step=0.1)
403
+ top_k = gr.Slider(label="Top-K πŸ”’", minimum=10, maximum=500,value=250, step=10)
404
+ top_p = gr.Slider(label="Top-P 🎰", minimum=0, maximum=1, value=0.9, step=0.05)
405
+ temperature = gr.Slider(label="Temperature πŸ”₯",minimum=0.1,maximum=2, value=1, step=0.1)
406
+ total_duration = gr.Radio (label="Length ⏳ (s)", choices=[30,60,90,120], value=30)
407
+ chunk_duration = gr.Slider(label="Chunk ⏱️ (s)", minimum=5, maximum=15, value=10, step=1)
408
+ crossfade_duration= gr.Slider(label="Crossfade 🎢 (ms)",minimum=100,maximum=2000,value=1000,step=100)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409
 
410
  gr.Markdown("### 🎡 Musical Controls")
411
  with gr.Group(elem_classes="group-container"):
412
+ bpm = gr.Slider(label="Tempo 🎡 (BPM)", minimum=60, maximum=180, value=120, step=1)
413
+ drum_beat = gr.Dropdown(label="Drum Beat πŸ₯",
414
+ choices=["none","standard rock","funk groove","techno kick","jazz swing"], value="none")
415
+ synthesizer= gr.Dropdown(label="Synthesizer 🎹",
416
+ choices=["none","analog synth","digital pad","arpeggiated synth"], value="none")
417
+ rhythmic_steps=gr.Dropdown(label="Rhythmic Steps πŸ‘£",
418
+ choices=["none","syncopated steps","steady steps","complex steps"], value="none")
419
+ bass_style = gr.Dropdown(label="Bass Style 🎸",
420
+ choices=["none","slap bass","deep bass","melodic bass"], value="none")
421
+ guitar_style=gr.Dropdown(label="Guitar Style 🎸",
422
+ choices=["none","distorted","clean","jangle"], value="none")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
 
424
  with gr.Row(elem_classes="action-buttons"):
425
  gen_btn = gr.Button("Generate Music πŸš€")
426
  clr_btn = gr.Button("Clear Inputs 🧹")
427
+
428
+ # OUTPUT
429
  with gr.Column(elem_classes="output-container"):
430
  gr.Markdown("### 🎧 Output")
431
+ out_audio = gr.Audio(label="Generated Track 🎡", type="filepath")
432
+ status = gr.Textbox(label="Status πŸ“’", interactive=False)
433
+
434
+ # ACTIONS
 
 
 
 
 
 
 
 
 
 
 
 
 
435
  gen_btn.click(
436
  generate_music,
437
+ inputs=[prompt_box, cfg_scale, top_k, top_p, temperature,
438
+ total_duration, chunk_duration, crossfade_duration,
439
+ bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style],
440
  outputs=[out_audio, status]
441
  )
442
  clr_btn.click(
443
  clear_inputs,
444
  inputs=None,
445
+ outputs=[prompt_box, cfg_scale, top_k, top_p, temperature,
446
+ total_duration, chunk_duration, crossfade_duration,
447
+ bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style]
448
  )
449
 
450
+ # ----------------------------------------------------------------------
451
+ # LAUNCH
452
+ # ----------------------------------------------------------------------
453
+ app = demo.launch(share=False, inbrowser=False, show_error=True)
454
+
455
+ # Disable OpenAPI docs (HF Spaces hardening)
456
  try:
457
  fastapi_app = demo._server.app
458
+ fastapi_app.docs_url = None
459
+ fastapi_app.redoc_url = None
460
  fastapi_app.openapi_url = None
461
  except Exception:
462
+ pass