File size: 8,680 Bytes
fdc5f70
545f8e1
 
 
 
 
 
 
 
 
80cc045
545f8e1
 
 
 
 
 
 
87e4401
2c690c6
857db5b
545f8e1
87e4401
545f8e1
 
80cc045
 
 
 
 
87e4401
80cc045
87e4401
545f8e1
779076d
 
545f8e1
e05183d
857db5b
87e4401
545f8e1
80cc045
545f8e1
 
 
 
 
 
 
 
 
 
 
 
80cc045
 
 
 
 
 
 
 
 
 
545f8e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80cc045
 
545f8e1
 
 
 
80cc045
 
 
f950faf
2c690c6
545f8e1
80cc045
545f8e1
 
 
 
 
 
 
80cc045
545f8e1
80cc045
 
 
 
545f8e1
 
 
 
80cc045
545f8e1
80cc045
 
545f8e1
 
 
c3aa73a
 
545f8e1
80cc045
2c690c6
545f8e1
 
 
c3aa73a
545f8e1
 
80cc045
 
 
c3aa73a
545f8e1
 
80cc045
545f8e1
 
fdc5f70
80cc045
 
 
 
545f8e1
 
 
 
80cc045
 
545f8e1
 
80cc045
 
545f8e1
80cc045
545f8e1
 
80cc045
545f8e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80cc045
545f8e1
 
80cc045
 
545f8e1
 
 
 
 
 
e05183d
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/env python3
"""
GhostAI Music Generator โ€” ZeroGPU Space
Streams facebook/musicgen-medium with dynamic GPU bursts.
"""

# 0๏ธโƒฃ  Import spaces *first* so CUDA isnโ€™t touched beforehand
import spaces                          # HF ZeroGPU decorator

# 1๏ธโƒฃ  Standard libs
import os, sys, gc, time, warnings, random, tempfile
import numpy as np, psutil

# 2๏ธโƒฃ  Torch (CPU wheels; ZeroGPU migrates tensors when needed)
import torch, torchaudio

# 3๏ธโƒฃ  Other deps
import gradio as gr
from pydub import AudioSegment
from audiocraft.models import MusicGen
from huggingface_hub import login
from torch.cuda.amp import autocast

# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# Torch <2.3 shim (transformers may call torch.get_default_device)
if not hasattr(torch, "get_default_device"):
    torch.get_default_device = lambda: torch.device(
        "cuda" if torch.cuda.is_available() else "cpu"
    )

warnings.filterwarnings("ignore")
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"

# ๐Ÿ”‘  Authenticate so we can pull the model
HF_TOKEN = os.getenv("HF_TOKEN")
if not HF_TOKEN:
    sys.exit("ERROR: Add HF_TOKEN as a secret in your Space.")
login(HF_TOKEN)

device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"ZeroGPU detected โ†’ initial device is {device.upper()}")

# ๐Ÿ“ฅ  Download model from Hub
print("Loading facebook/musicgen-medium โ€ฆ (first run may take ~6 GB download)")
musicgen = MusicGen.get_pretrained("facebook/musicgen-medium")
musicgen.set_generation_params(duration=10, two_step_cfg=False)
SAMPLE_RATE = musicgen.sample_rate


# โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
# โ”‚ Prompt helpers (kept exactly from your original script)      โ”‚
# โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
def _p(base,bpm,dr,syn,st,bass,gtr,dflt_bass,dflt_gtr,flow):
    step = f" with {st}" if st!="none" else flow.format(bpm=bpm)
    dr   = f", {dr} drums"          if dr!="none" else ""
    syn  = f", {syn} accents"       if syn!="none" else ""
    bass = f", {bass}"              if bass!="none" else dflt_bass
    gtr  = f", {gtr} guitar riffs"  if gtr!="none" else dflt_gtr
    return f"{base}{bass}{gtr}{dr}{syn}{step} at {bpm} BPM."

def set_red_hot_chili_peppers_prompt(bpm,dr,syn,st,bass,gtr):
    return _p("Instrumental funk rock",bpm,dr,syn,st,bass,gtr,
              ", groovy basslines",", syncopated guitar riffs",
              "{bpm} BPM funky flow" if bpm>120 else "groovy rhythmic flow")
def set_nirvana_grunge_prompt(bpm,dr,syn,st,bass,gtr):
    return _p("Instrumental grunge",bpm,dr,syn,st,bass,gtr,
              ", melodic basslines",", raw distorted guitar riffs",
              "{bpm} BPM grungy pulse" if bpm>120 else "grungy rhythmic pulse")
# โ€ฆ include your other genre functions unchanged โ€ฆ

# Audio FX
def apply_eq(s):   return s.low_pass_filter(8000).high_pass_filter(80)
def apply_fade(s): return s.fade_in(1000).fade_out(1000)

def log(stage=""):
    if stage: print(f"โ”€โ”€ {stage} โ”€โ”€")
    if torch.cuda.is_available():
        alloc = torch.cuda.memory_allocated()/1024**3
        res   = torch.cuda.memory_reserved()/1024**3
        print(f"GPU mem alloc {alloc:.2f} GB  reserved {res:.2f} GB")
    print(f"CPU mem {psutil.virtual_memory().percent}% used")


# โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
# โ”‚  Core generator โ€” wrapped with @spaces.GPU                   โ”‚
# โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
@spaces.GPU
def generate_music(prompt,cfg,k,p,temp,
                   total_len,chunk_len,xfade,
                   bpm,dr,syn,step,bass,gtr):

    if not prompt.strip():
        return None, "โš ๏ธ Prompt is empty."

    total_len = int(total_len)
    chunk_len = max(5, min(int(chunk_len), 15))
    n_chunks  = max(1, total_len // chunk_len)
    chunk_len = total_len / n_chunks
    overlap   = min(1.0, xfade / 1000.0)
    render    = chunk_len + overlap
    pieces    = []

    torch.manual_seed(42); np.random.seed(42)

    t0 = time.time()
    for i in range(n_chunks):
        log(f"before chunk {i+1}")
        musicgen.set_generation_params(
            duration=render, use_sampling=True,
            top_k=k, top_p=p, temperature=temp, cfg_coef=cfg
        )
        with torch.no_grad(), autocast():
            audio = musicgen.generate([prompt], progress=False)[0]

        audio = audio.cpu().float()
        if audio.dim()==1:      audio = audio.repeat(2,1)
        elif audio.shape[0]==1: audio = audio.repeat(2,1)
        elif audio.shape[0]!=2: audio = audio[:1].repeat(2,1)

        with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
            torchaudio.save(tmp.name, audio, SAMPLE_RATE)
            seg = AudioSegment.from_wav(tmp.name)
        os.unlink(tmp.name)
        pieces.append(seg)
        torch.cuda.empty_cache(); gc.collect()
        log(f"after chunk {i+1}")

    track = pieces[0]
    for seg in pieces[1:]:
        track = track.append(seg, crossfade=xfade)
    track = track[: total_len*1000]
    track = apply_fade(apply_eq(track).normalize(headroom=-9.0))

    out_file = "output_cleaned.mp3"
    track.export(out_file, format="mp3", bitrate="128k",
                 tags={"title":"GhostAI Track","artist":"GhostAI"})
    log("final"); print(f"Total {time.time()-t0:.1f}s")
    return out_file, "โœ… Done!"

def clear_inputs():
    return ("",3.0,250,0.9,1.0,30,10,1000,
            120,"none","none","none","none","none")

# โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
# โ”‚  Gradio Blocks UI with your CSS & controls                   โ”‚
# โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
css = "body{background:#0A0A0A;color:#E0E0E0;font-family:'Orbitron',sans-serif}"

with gr.Blocks(css=css) as demo:
    gr.HTML("<h1 style='text-align:center'>๐Ÿ‘ป GhostAI Music Generator</h1>")
    prompt = gr.Textbox(label="Prompt", lines=4)

    with gr.Row():
        gr.Button("RHCP ๐ŸŒถ๏ธ").click(set_red_hot_chili_peppers_prompt,
            inputs=[gr.State(120),"none","none","none","none","none"],
            outputs=prompt)
        gr.Button("Nirvana ๐ŸŽธ").click(set_nirvana_grunge_prompt,
            inputs=[gr.State(120),"none","none","none","none","none"],
            outputs=prompt)
        # add more genre buttons here โ€ฆ

    cfg   = gr.Slider(1,10,3,label="CFG")
    top_k = gr.Slider(10,500,250,step=10,label="Top-K")
    top_p = gr.Slider(0,1,0.9,step=0.05,label="Top-P")
    temp  = gr.Slider(0.1,2,1,step=0.1,label="Temperature")
    length= gr.Radio([30,60,90,120],value=30,label="Length (s)")
    chunk = gr.Slider(5,15,10,step=1,label="Chunk (s)")
    xfade = gr.Slider(100,2000,1000,step=100,label="Cross-fade (ms)")

    bpm   = gr.Slider(60,180,120,label="BPM")
    drum  = gr.Dropdown(["none","standard rock","funk groove","techno kick","jazz swing"],"none","Drum")
    synth = gr.Dropdown(["none","analog synth","digital pad","arpeggiated synth"],"none","Synth")
    steps = gr.Dropdown(["none","syncopated steps","steady steps","complex steps"],"none","Steps")
    bass  = gr.Dropdown(["none","slap bass","deep bass","melodic bass"],"none","Bass")
    gtr   = gr.Dropdown(["none","distorted","clean","jangle"],"none","Guitar")

    gen = gr.Button("Generate ๐ŸŽถ")
    clr = gr.Button("Clear ๐Ÿงน")
    audio = gr.Audio(type="filepath")
    status= gr.Textbox(interactive=False)

    gen.click(generate_music,
        inputs=[prompt,cfg,top_k,top_p,temp,length,chunk,xfade,
                bpm,drum,synth,steps,bass,gtr],
        outputs=[audio,status])
    clr.click(clear_inputs,None,
        [prompt,cfg,top_k,top_p,temp,length,chunk,xfade,
         bpm,drum,synth,steps,bass,gtr])

demo.launch(share=False)