multimodalart HF Staff commited on
Commit
08029ce
·
1 Parent(s): 2e577a3

[Admin maintenance] Migrate to ZeroGPU (#105)

Browse files

- [Admin maintenance] Migrate to ZeroGPU (6a20daacc63966a656e3cf6e9aa465f969c98df3)

Files changed (3) hide show
  1. README.md +2 -2
  2. demos/musicgen_app.py +65 -58
  3. requirements.txt +9 -9
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
  title: "MusicGen"
3
- python_version: "3.9"
4
  tags:
5
  - "music generation"
6
  - "language models"
@@ -10,7 +10,7 @@ emoji: 🎵
10
  colorFrom: gray
11
  colorTo: blue
12
  sdk: gradio
13
- sdk_version: 3.34.0
14
  pinned: true
15
  license: "cc-by-nc-4.0"
16
  disable_embedding: true
 
1
  ---
2
  title: "MusicGen"
3
+ python_version: "3.10"
4
  tags:
5
  - "music generation"
6
  - "language models"
 
10
  colorFrom: gray
11
  colorTo: blue
12
  sdk: gradio
13
+ sdk_version: 5.49.1
14
  pinned: true
15
  license: "cc-by-nc-4.0"
16
  disable_embedding: true
demos/musicgen_app.py CHANGED
@@ -8,7 +8,19 @@
8
  # also released under the MIT license.
9
 
10
  import argparse
 
 
11
  from concurrent.futures import ProcessPoolExecutor
 
 
 
 
 
 
 
 
 
 
12
  import logging
13
  import os
14
  from pathlib import Path
@@ -82,23 +94,41 @@ class FileCleaner:
82
  file_cleaner = FileCleaner()
83
 
84
 
85
- def make_waveform(*args, **kwargs):
86
- # Further remove some warnings.
87
- be = time.time()
88
- with warnings.catch_warnings():
89
- warnings.simplefilter('ignore')
90
- out = gr.make_waveform(*args, **kwargs)
91
- print("Make a video took", time.time() - be)
92
- return out
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
 
95
  def load_model(version='facebook/musicgen-melody'):
96
  global MODEL
97
- print("Loading model", version)
98
- if MODEL is None or MODEL.name != version:
99
- del MODEL
100
- MODEL = None # in case loading would crash
101
- MODEL = MusicGen.get_pretrained(version)
102
 
103
 
104
  def load_diffusion():
@@ -152,32 +182,28 @@ def _do_predictions(texts, melodies, duration, progress=False, gradio_progress=N
152
  outputs_diffusion = rearrange(outputs_diffusion, '(s b) c t -> b (s c) t', s=2)
153
  outputs = torch.cat([outputs[0], outputs_diffusion], dim=0)
154
  outputs = outputs.detach().cpu().float()
155
- pending_videos = []
156
  out_wavs = []
157
  for output in outputs:
158
  with NamedTemporaryFile("wb", suffix=".wav", delete=False) as file:
159
  audio_write(
160
  file.name, output, MODEL.sample_rate, strategy="loudness",
161
  loudness_headroom_db=16, loudness_compressor=True, add_suffix=False)
162
- pending_videos.append(pool.submit(make_waveform, file.name))
163
  out_wavs.append(file.name)
164
  file_cleaner.add(file.name)
165
- out_videos = [pending_video.result() for pending_video in pending_videos]
166
- for video in out_videos:
167
- file_cleaner.add(video)
168
  print("batch finished", len(texts), time.time() - be)
169
  print("Tempfiles currently stored: ", len(file_cleaner.files))
170
- return out_videos, out_wavs
171
 
172
 
173
  def predict_batched(texts, melodies):
174
  max_text_length = 512
175
  texts = [text[:max_text_length] for text in texts]
176
  load_model('facebook/musicgen-stereo-melody')
177
- res = _do_predictions(texts, melodies, BATCHED_DURATION)
178
- return res
179
 
180
 
 
181
  def predict_full(model, model_path, decoder, text, melody, duration, topk, topp, temperature, cfg_coef, progress=gr.Progress()):
182
  global INTERRUPTING
183
  global USE_DIFFUSION
@@ -217,27 +243,17 @@ def predict_full(model, model_path, decoder, text, melody, duration, topk, topp,
217
  raise gr.Error("Interrupted.")
218
  MODEL.set_custom_progress_callback(_progress)
219
 
220
- videos, wavs = _do_predictions(
221
  [text], [melody], duration, progress=True,
222
  top_k=topk, top_p=topp, temperature=temperature, cfg_coef=cfg_coef,
223
  gradio_progress=progress)
224
  if USE_DIFFUSION:
225
- return videos[0], wavs[0], videos[1], wavs[1]
226
- return videos[0], wavs[0], None, None
227
-
228
-
229
- def toggle_audio_src(choice):
230
- if choice == "mic":
231
- return gr.update(source="microphone", value=None, label="Microphone")
232
- else:
233
- return gr.update(source="upload", value=None, label="File")
234
 
235
 
236
  def toggle_diffusion(choice):
237
- if choice == "MultiBand_Diffusion":
238
- return [gr.update(visible=True)] * 2
239
- else:
240
- return [gr.update(visible=False)] * 2
241
 
242
 
243
  def ui_full(launch_kwargs):
@@ -254,11 +270,9 @@ def ui_full(launch_kwargs):
254
  with gr.Column():
255
  with gr.Row():
256
  text = gr.Text(label="Input Text", interactive=True)
257
- with gr.Column():
258
- radio = gr.Radio(["file", "mic"], value="file",
259
- label="Condition on a melody (optional) File or Mic")
260
- melody = gr.Audio(source="upload", type="numpy", label="File",
261
- interactive=True, elem_id="melody-input")
262
  with gr.Row():
263
  submit = gr.Button("Submit")
264
  # Adapted from https://github.com/rkfg/audiocraft/blob/long/app.py, MIT license.
@@ -282,15 +296,12 @@ def ui_full(launch_kwargs):
282
  temperature = gr.Number(label="Temperature", value=1.0, interactive=True)
283
  cfg_coef = gr.Number(label="Classifier Free Guidance", value=3.0, interactive=True)
284
  with gr.Column():
285
- output = gr.Video(label="Generated Music")
286
- audio_output = gr.Audio(label="Generated Music (wav)", type='filepath')
287
- diffusion_output = gr.Video(label="MultiBand Diffusion Decoder")
288
- audio_diffusion = gr.Audio(label="MultiBand Diffusion Decoder (wav)", type='filepath')
289
- submit.click(toggle_diffusion, decoder, [diffusion_output, audio_diffusion], queue=False,
290
  show_progress=False).then(predict_full, inputs=[model, model_path, decoder, text, melody, duration, topk, topp,
291
  temperature, cfg_coef],
292
- outputs=[output, audio_output, diffusion_output, audio_diffusion])
293
- radio.change(toggle_audio_src, radio, [melody], queue=False, show_progress=False)
294
 
295
  gr.Examples(
296
  fn=predict_full,
@@ -333,7 +344,7 @@ def ui_full(launch_kwargs):
333
  ],
334
  ],
335
  inputs=[text, melody, model, decoder],
336
- outputs=[output]
337
  )
338
  gr.Markdown(
339
  """
@@ -404,19 +415,15 @@ def ui_batched(launch_kwargs):
404
  with gr.Column():
405
  with gr.Row():
406
  text = gr.Text(label="Describe your music", lines=2, interactive=True)
407
- with gr.Column():
408
- radio = gr.Radio(["file", "mic"], value="file",
409
- label="Condition on a melody (optional) File or Mic")
410
- melody = gr.Audio(source="upload", type="numpy", label="File",
411
- interactive=True, elem_id="melody-input")
412
  with gr.Row():
413
  submit = gr.Button("Generate")
414
  with gr.Column():
415
- output = gr.Video(label="Generated Music")
416
- audio_output = gr.Audio(label="Generated Music (wav)", type='filepath')
417
  submit.click(predict_batched, inputs=[text, melody],
418
- outputs=[output, audio_output], batch=True, max_batch_size=MAX_BATCH_SIZE)
419
- radio.change(toggle_audio_src, radio, [melody], queue=False, show_progress=False)
420
  gr.Examples(
421
  fn=predict_batched,
422
  examples=[
@@ -442,7 +449,7 @@ def ui_batched(launch_kwargs):
442
  ],
443
  ],
444
  inputs=[text, melody],
445
- outputs=[output]
446
  )
447
  gr.Markdown("""
448
  ### More details
 
8
  # also released under the MIT license.
9
 
10
  import argparse
11
+ import subprocess
12
+ import sys as _sys
13
  from concurrent.futures import ProcessPoolExecutor
14
+
15
+ # audiocraft pulls demucs (for melody conditioning); its torchaudio<2.1 pin
16
+ # would drag torch back and break `spaces`. Install demucs without deps so the
17
+ # constraint doesn't propagate.
18
+ subprocess.run(
19
+ [_sys.executable, "-m", "pip", "install", "--no-deps", "demucs"],
20
+ check=True,
21
+ )
22
+
23
+ import spaces
24
  import logging
25
  import os
26
  from pathlib import Path
 
94
  file_cleaner = FileCleaner()
95
 
96
 
97
+
98
+
99
+ ALL_MODELS = [
100
+ 'facebook/musicgen-melody',
101
+ 'facebook/musicgen-medium',
102
+ 'facebook/musicgen-small',
103
+ 'facebook/musicgen-large',
104
+ 'facebook/musicgen-melody-large',
105
+ 'facebook/musicgen-stereo-small',
106
+ 'facebook/musicgen-stereo-medium',
107
+ 'facebook/musicgen-stereo-melody',
108
+ 'facebook/musicgen-stereo-large',
109
+ 'facebook/musicgen-stereo-melody-large',
110
+ ]
111
+
112
+
113
+ def _load_to_cuda(name):
114
+ print(f"Preloading {name} to cuda")
115
+ m = MusicGen.get_pretrained(name, device='cuda')
116
+ m.compression_model.to('cuda')
117
+ m.lm.to('cuda')
118
+ return m
119
+
120
+
121
+ # All MusicGen variants (LM + EncodeC) fit on a 48GB ZeroGPU. Preload them once
122
+ # on CUDA at module load so generation switches between models without
123
+ # re-downloading or re-instantiating per request. `import spaces` hijacks CUDA,
124
+ # so the .to('cuda') here gets routed to the real device.
125
+ MODELS = {name: _load_to_cuda(name) for name in ALL_MODELS}
126
 
127
 
128
  def load_model(version='facebook/musicgen-melody'):
129
  global MODEL
130
+ MODEL = MODELS[version]
131
+ print("Selected model", version)
 
 
 
132
 
133
 
134
  def load_diffusion():
 
182
  outputs_diffusion = rearrange(outputs_diffusion, '(s b) c t -> b (s c) t', s=2)
183
  outputs = torch.cat([outputs[0], outputs_diffusion], dim=0)
184
  outputs = outputs.detach().cpu().float()
 
185
  out_wavs = []
186
  for output in outputs:
187
  with NamedTemporaryFile("wb", suffix=".wav", delete=False) as file:
188
  audio_write(
189
  file.name, output, MODEL.sample_rate, strategy="loudness",
190
  loudness_headroom_db=16, loudness_compressor=True, add_suffix=False)
 
191
  out_wavs.append(file.name)
192
  file_cleaner.add(file.name)
 
 
 
193
  print("batch finished", len(texts), time.time() - be)
194
  print("Tempfiles currently stored: ", len(file_cleaner.files))
195
+ return out_wavs
196
 
197
 
198
  def predict_batched(texts, melodies):
199
  max_text_length = 512
200
  texts = [text[:max_text_length] for text in texts]
201
  load_model('facebook/musicgen-stereo-melody')
202
+ wavs = _do_predictions(texts, melodies, BATCHED_DURATION)
203
+ return [wavs]
204
 
205
 
206
+ @spaces.GPU(duration=120)
207
  def predict_full(model, model_path, decoder, text, melody, duration, topk, topp, temperature, cfg_coef, progress=gr.Progress()):
208
  global INTERRUPTING
209
  global USE_DIFFUSION
 
243
  raise gr.Error("Interrupted.")
244
  MODEL.set_custom_progress_callback(_progress)
245
 
246
+ wavs = _do_predictions(
247
  [text], [melody], duration, progress=True,
248
  top_k=topk, top_p=topp, temperature=temperature, cfg_coef=cfg_coef,
249
  gradio_progress=progress)
250
  if USE_DIFFUSION:
251
+ return wavs[0], wavs[1]
252
+ return wavs[0], None
 
 
 
 
 
 
 
253
 
254
 
255
  def toggle_diffusion(choice):
256
+ return [gr.update(visible=choice == "MultiBand_Diffusion")]
 
 
 
257
 
258
 
259
  def ui_full(launch_kwargs):
 
270
  with gr.Column():
271
  with gr.Row():
272
  text = gr.Text(label="Input Text", interactive=True)
273
+ melody = gr.Audio(sources=["upload", "microphone"], type="numpy",
274
+ label="Condition on a melody (optional)",
275
+ interactive=True, elem_id="melody-input")
 
 
276
  with gr.Row():
277
  submit = gr.Button("Submit")
278
  # Adapted from https://github.com/rkfg/audiocraft/blob/long/app.py, MIT license.
 
296
  temperature = gr.Number(label="Temperature", value=1.0, interactive=True)
297
  cfg_coef = gr.Number(label="Classifier Free Guidance", value=3.0, interactive=True)
298
  with gr.Column():
299
+ audio_output = gr.Audio(label="Generated Music", type='filepath')
300
+ audio_diffusion = gr.Audio(label="MultiBand Diffusion Decoder", type='filepath')
301
+ submit.click(toggle_diffusion, decoder, [audio_diffusion], queue=False,
 
 
302
  show_progress=False).then(predict_full, inputs=[model, model_path, decoder, text, melody, duration, topk, topp,
303
  temperature, cfg_coef],
304
+ outputs=[audio_output, audio_diffusion])
 
305
 
306
  gr.Examples(
307
  fn=predict_full,
 
344
  ],
345
  ],
346
  inputs=[text, melody, model, decoder],
347
+ outputs=[audio_output]
348
  )
349
  gr.Markdown(
350
  """
 
415
  with gr.Column():
416
  with gr.Row():
417
  text = gr.Text(label="Describe your music", lines=2, interactive=True)
418
+ melody = gr.Audio(sources=["upload", "microphone"], type="numpy",
419
+ label="Condition on a melody (optional)",
420
+ interactive=True, elem_id="melody-input")
 
 
421
  with gr.Row():
422
  submit = gr.Button("Generate")
423
  with gr.Column():
424
+ audio_output = gr.Audio(label="Generated Music", type='filepath')
 
425
  submit.click(predict_batched, inputs=[text, melody],
426
+ outputs=[audio_output], batch=True, max_batch_size=MAX_BATCH_SIZE)
 
427
  gr.Examples(
428
  fn=predict_batched,
429
  examples=[
 
449
  ],
450
  ],
451
  inputs=[text, melody],
452
+ outputs=[audio_output]
453
  )
454
  gr.Markdown("""
455
  ### More details
requirements.txt CHANGED
@@ -1,23 +1,23 @@
1
- # please make sure you have already a pytorch install that is cuda enabled!
 
2
  av
3
  einops
4
  flashy>=0.0.1
5
  hydra-core>=1.1
6
  hydra_colorlog
7
  julius
 
 
 
 
8
  num2words
9
- numpy==1.26.4
10
  sentencepiece
11
- spacy==3.5.2
12
- torch<2.1.0
13
- torchaudio<2.1.0
14
- huggingface_hub
15
  tqdm
16
- transformers>=4.31.0 # need Encodec there.
17
  xformers
18
- demucs
19
  librosa
20
- gradio_client==0.2.6
21
  torchmetrics
22
  encodec
23
  protobuf
 
1
+ torch==2.8.0
2
+ torchaudio==2.8.0
3
  av
4
  einops
5
  flashy>=0.0.1
6
  hydra-core>=1.1
7
  hydra_colorlog
8
  julius
9
+ lameenc
10
+ openunmix
11
+ dora-search
12
+ pyyaml
13
  num2words
14
+ numpy
15
  sentencepiece
16
+ spacy
 
 
 
17
  tqdm
18
+ transformers>=4.31.0
19
  xformers
 
20
  librosa
 
21
  torchmetrics
22
  encodec
23
  protobuf