ford442 commited on
Commit
e8ee3b3
·
verified ·
1 Parent(s): 1153954

Update demos/musicgen_app.py

Browse files
Files changed (1) hide show
  1. demos/musicgen_app.py +112 -8
demos/musicgen_app.py CHANGED
@@ -30,8 +30,8 @@ torch.backends.cuda.matmul.allow_fp16_reduced_precision_reduction = False
30
  torch.backends.cudnn.allow_tf32 = False
31
  torch.backends.cudnn.deterministic = False
32
  torch.backends.cudnn.benchmark = False
33
- # torch.backends.cuda.preferred_blas_library="cublas"
34
- # torch.backends.cuda.preferred_linalg_library="cusolver"
35
  torch.set_float32_matmul_precision("highest")
36
 
37
  class FileCleaner:
@@ -53,6 +53,103 @@ class FileCleaner:
53
 
54
  file_cleaner = FileCleaner()
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  def convert_wav_to_mp4(wav_path, output_path=None):
57
  """Converts a WAV file to a waveform MP4 video using ffmpeg."""
58
  if output_path is None:
@@ -489,9 +586,16 @@ if __name__ == '__main__':
489
  if args.share:
490
  launch_kwargs['share'] = args.share
491
  logging.basicConfig(level=logging.INFO, stream=sys.stderr)
492
- # Added predictor shutdown
493
- try:
494
- ui_full(launch_kwargs)
495
- finally:
496
- if _predictor is not None:
497
- _predictor.shutdown()
 
 
 
 
 
 
 
 
30
  torch.backends.cudnn.allow_tf32 = False
31
  torch.backends.cudnn.deterministic = False
32
  torch.backends.cudnn.benchmark = False
33
+ torch.backends.cuda.preferred_blas_library="cublas"
34
+ torch.backends.cuda.preferred_linalg_library="cusolver"
35
  torch.set_float32_matmul_precision("highest")
36
 
37
  class FileCleaner:
 
53
 
54
  file_cleaner = FileCleaner()
55
 
56
+
57
+ # We'll load a model globally to be shared by our new UI tab
58
+ # This simplifies things by avoiding the Predictor class for this specific feature.
59
+ print("Loading model for segmented generation...")
60
+ MODEL = MusicGen.get_pretrained("facebook/musicgen-melody", device='cuda')
61
+ print("Model loaded.")
62
+
63
+ @spaces.GPU(duration=90)
64
+ def predict_segment(prompt, seed, current_segment, duration_per_segment):
65
+ """
66
+ This is the core prediction function for our new UI tab.
67
+ It calls the generate_segment method we created earlier.
68
+ """
69
+ print(f"Requesting to generate segment {current_segment} with seed {seed}.")
70
+ # Convert duration to token length for the model
71
+ # Note: The actual frame rate might differ, but this is a close approximation.
72
+ max_segment_len = int(duration_per_segment * 50)
73
+
74
+ # If the seed is -1 or None, it means we should start with a random seed.
75
+ # The generate_segment function handles the logic of creating a new seed for segment 1.
76
+ seed_to_use = None if seed == -1 else int(seed)
77
+
78
+ # Call the method we added to the LMModel
79
+ # Note the path: MODEL.lm.generate_segment
80
+ full_codes, updated_seed = MODEL.lm.generate_segment(
81
+ segment=int(current_segment),
82
+ seed=seed_to_use,
83
+ prompt_text=prompt,
84
+ max_segment_len=max_segment_len,
85
+ # You can pass other generation params here if you add them to the UI
86
+ temp=1.0,
87
+ top_k=250,
88
+ cfg_coef=3.0,
89
+ )
90
+
91
+ # Decode the *entire* audio generated so far to a waveform
92
+ audio_wav = MODEL.compression_model.decode(full_codes.to('cuda'))
93
+ audio_wav = audio_wav.detach().cpu()
94
+
95
+ # Save the waveform to a temporary file for the Gradio Audio component
96
+ with NamedTemporaryFile("wb", suffix=".wav", delete=False) as file:
97
+ audio_write(
98
+ file.name, audio_wav[0], MODEL.sample_rate, strategy="loudness",
99
+ loudness_headroom_db=16, loudness_compressor=True, add_suffix=False
100
+ )
101
+ file_cleaner.add(file.name)
102
+
103
+ # We must return values for all the outputs of the button's .click() event:
104
+ # 1. The audio file path for the gr.Audio component.
105
+ # 2. The updated seed for the gr.Number component.
106
+ # 3. The next segment number (current + 1) for the gr.Number state.
107
+ # 4. A new label for the button to guide the user.
108
+ return file.name, updated_seed, current_segment + 1, gr.update(value=f"Generate Segment {current_segment + 1}")
109
+
110
+
111
+ def reset_segmented_ui():
112
+ """Resets the UI state for starting a new song."""
113
+ return None, -1, 1, gr.update(value="Generate Segment 1")
114
+
115
+
116
+ def ui_segmented():
117
+ """Builds the Gradio UI for the new 'Long / Segmented Generation' tab."""
118
+ with gr.Blocks() as interface:
119
+ gr.Markdown("## Long / Segmented Generation\nGenerate music longer than the time limit by creating it in segments. The state is saved to a file after each segment.")
120
+
121
+ with gr.Row():
122
+ prompt = gr.Text(label="Prompt", placeholder="e.g., An epic cinematic orchestral score")
123
+ # The Seed field is critical for linking segments. We use -1 to signify a random start.
124
+ seed = gr.Number(value=-1, label="Seed (-1 for random start)")
125
+
126
+ duration = gr.Slider(label="Duration PER Segment (seconds)", minimum=10, maximum=90, value=30, step=5)
127
+
128
+ # This hidden Number component will keep track of which segment we're on
129
+ current_segment = gr.Number(value=1, visible=False)
130
+
131
+ with gr.Row():
132
+ run_button = gr.Button("Generate Segment 1")
133
+ reset_button = gr.Button("Reset & Start New Song")
134
+
135
+ audio_output = gr.Audio(label="Full Generated Music So Far", type='filepath')
136
+
137
+ # --- Wire up the buttons ---
138
+ run_button.click(
139
+ fn=predict_segment,
140
+ inputs=[prompt, seed, current_segment, duration],
141
+ # The outputs update the audio player, the seed box, the hidden segment counter, and the button label
142
+ outputs=[audio_output, seed, current_segment, run_button]
143
+ )
144
+
145
+ reset_button.click(
146
+ fn=reset_segmented_ui,
147
+ inputs=[],
148
+ outputs=[audio_output, seed, current_segment, run_button]
149
+ )
150
+ return interface
151
+
152
+
153
  def convert_wav_to_mp4(wav_path, output_path=None):
154
  """Converts a WAV file to a waveform MP4 video using ffmpeg."""
155
  if output_path is None:
 
586
  if args.share:
587
  launch_kwargs['share'] = args.share
588
  logging.basicConfig(level=logging.INFO, stream=sys.stderr)
589
+
590
+ # Build the two interfaces
591
+ original_interface = ui_full({})
592
+ segmented_interface = ui_segmented()
593
+
594
+ # Combine them in a tabbed layout
595
+ tabbed_interface = gr.TabbedInterface(
596
+ [original_interface, segmented_interface],
597
+ ["Single Generation", "Long / Segmented Generation"]
598
+ )
599
+
600
+ # Launch the final combined app
601
+ tabbed_interface.queue().launch(**launch_kwargs)