fffiloni commited on
Commit
68bdff7
·
verified ·
1 Parent(s): d52b274

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -43
app.py CHANGED
@@ -8,6 +8,8 @@ from scipy.io.wavfile import write
8
  from transformers import pipeline
9
 
10
 
 
 
11
  MODEL_NAME = "openai/whisper-large-v3-turbo"
12
  BATCH_SIZE = 8
13
 
@@ -18,19 +20,22 @@ pipe = pipeline(
18
  model=MODEL_NAME,
19
  chunk_length_s=30,
20
  device=device,
 
21
  )
22
 
23
 
24
- def split_process(audio, chosen_out_track="vocals", progress=gr.Progress(track_tqdm=True)):
25
  if audio is None:
26
- raise gr.Error("Upload an audio file first.")
 
 
27
 
28
  os.makedirs("out", exist_ok=True)
29
 
30
  progress(0.02, desc="Preparing audio...")
31
  write("test.wav", audio[0], audio[1])
32
 
33
- progress(0.05, desc="Starting Demucs...")
34
 
35
  cmd = [
36
  "python3",
@@ -56,7 +61,7 @@ def split_process(audio, chosen_out_track="vocals", progress=gr.Progress(track_t
56
  percent_re = re.compile(r"(\d{1,3})%")
57
  completed_bars = 0
58
  last_percent = 0
59
- max_bars = 4 # mdx_extra_q = bag of 4 Demucs models
60
  logs = []
61
 
62
  for line in process.stdout:
@@ -93,30 +98,32 @@ def split_process(audio, chosen_out_track="vocals", progress=gr.Progress(track_t
93
  f"{''.join(logs)[-2000:]}"
94
  )
95
 
96
- tracks = {
97
- "vocals": "./out/mdx_extra_q/test/vocals.wav",
98
- "bass": "./out/mdx_extra_q/test/bass.wav",
99
- "drums": "./out/mdx_extra_q/test/drums.wav",
100
- "other": "./out/mdx_extra_q/test/other.wav",
101
- "all-in": "test.wav",
102
- }
103
-
104
- output_path = tracks.get(chosen_out_track)
105
-
106
- if output_path is None:
107
  raise gr.Error(f"Unknown output track: {chosen_out_track}")
108
 
109
  if not os.path.exists(output_path):
110
  raise gr.Error(f"Expected output file was not created: {output_path}")
111
 
112
- progress(0.90, desc="Demucs separation complete.")
113
 
114
  return output_path
115
 
116
 
117
- def transcribe(inputs, task="transcribe"):
118
  if inputs is None:
119
- raise gr.Error("No audio file found.")
 
 
120
 
121
  result = pipe(
122
  inputs,
@@ -128,53 +135,107 @@ def transcribe(inputs, task="transcribe"):
128
  return result["text"]
129
 
130
 
131
- def infer(audio, progress=gr.Progress(track_tqdm=True)):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  progress(0.0, desc="Starting...")
133
 
134
- vocals_path = split_process(
135
- audio,
136
- chosen_out_track="vocals",
 
137
  progress=progress,
138
  )
139
 
 
 
 
140
  progress(0.92, desc="Transcribing vocals with Whisper...")
141
- lyrics = transcribe(vocals_path, task="transcribe")
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  progress(1.0, desc="Done.")
144
 
145
- return vocals_path, lyrics
146
 
147
 
148
  css = """
149
  #col-container {
150
- max-width: 780px;
151
  margin-left: auto;
152
  margin-right: auto;
153
  }
154
-
155
- a {
156
- text-decoration-line: underline;
157
- font-weight: 600;
158
- }
159
  """
160
 
161
 
162
  with gr.Blocks() as demo:
163
  with gr.Column(elem_id="col-container"):
164
- gr.Markdown(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  """
166
- # Music To Lyrics
167
-
168
- Upload a song and get the lyrics.
169
-
170
- The app first separates the vocals with Demucs, then transcribes them with Whisper.
171
- """
172
  )
173
 
174
  song_in = gr.Audio(
175
  label="Song input",
176
  type="numpy",
177
- sources=["upload"],
178
  )
179
 
180
  getlyrics_btn = gr.Button("Get Lyrics!")
@@ -182,11 +243,11 @@ The app first separates the vocals with Demucs, then transcribes them with Whisp
182
  vocals_out = gr.Audio(label="Vocals Only")
183
  lyrics_res = gr.Textbox(label="Lyrics")
184
 
185
- getlyrics_btn.click(
186
- fn=infer,
187
- inputs=[song_in],
188
- outputs=[vocals_out, lyrics_res],
189
- )
190
 
191
 
192
  demo.queue().launch(css=css, ssr_mode=False)
 
8
  from transformers import pipeline
9
 
10
 
11
+ hf_token = os.environ.get("HF_TOKEN")
12
+
13
  MODEL_NAME = "openai/whisper-large-v3-turbo"
14
  BATCH_SIZE = 8
15
 
 
20
  model=MODEL_NAME,
21
  chunk_length_s=30,
22
  device=device,
23
+ token=hf_token,
24
  )
25
 
26
 
27
+ def split_process(audio, chosen_out_track, progress=gr.Progress(track_tqdm=True)):
28
  if audio is None:
29
+ raise gr.Error(
30
+ "No audio file submitted! Please upload or record an audio file before submitting your request."
31
+ )
32
 
33
  os.makedirs("out", exist_ok=True)
34
 
35
  progress(0.02, desc="Preparing audio...")
36
  write("test.wav", audio[0], audio[1])
37
 
38
+ progress(0.05, desc="Starting vocal separation...")
39
 
40
  cmd = [
41
  "python3",
 
61
  percent_re = re.compile(r"(\d{1,3})%")
62
  completed_bars = 0
63
  last_percent = 0
64
+ max_bars = 4
65
  logs = []
66
 
67
  for line in process.stdout:
 
98
  f"{''.join(logs)[-2000:]}"
99
  )
100
 
101
+ if chosen_out_track == "vocals":
102
+ output_path = "./out/mdx_extra_q/test/vocals.wav"
103
+ elif chosen_out_track == "bass":
104
+ output_path = "./out/mdx_extra_q/test/bass.wav"
105
+ elif chosen_out_track == "drums":
106
+ output_path = "./out/mdx_extra_q/test/drums.wav"
107
+ elif chosen_out_track == "other":
108
+ output_path = "./out/mdx_extra_q/test/other.wav"
109
+ elif chosen_out_track == "all-in":
110
+ output_path = "test.wav"
111
+ else:
112
  raise gr.Error(f"Unknown output track: {chosen_out_track}")
113
 
114
  if not os.path.exists(output_path):
115
  raise gr.Error(f"Expected output file was not created: {output_path}")
116
 
117
+ progress(0.90, desc="Vocal separation complete.")
118
 
119
  return output_path
120
 
121
 
122
+ def transcribe(inputs, task):
123
  if inputs is None:
124
+ raise gr.Error(
125
+ "No audio file submitted! Please upload or record an audio file before submitting your request."
126
+ )
127
 
128
  result = pipe(
129
  inputs,
 
135
  return result["text"]
136
 
137
 
138
+ def format_lyrics(text):
139
+ if not text:
140
+ return ""
141
+
142
+ # Remove unwanted subtitle artifacts
143
+ text = re.sub(
144
+ r"Sous-?titrage Société Radio-Canada",
145
+ "",
146
+ text,
147
+ flags=re.IGNORECASE,
148
+ )
149
+
150
+ # Remove repeated newlines
151
+ text = re.sub(r"\n+", "\n", text).strip()
152
+
153
+ # Insert a newline before capital letters, like in the original app
154
+ formatted_text = re.sub(r"(?<!^)([A-Z])", r"\n\1", text)
155
+
156
+ # Remove leading whitespace on each line
157
+ formatted_text = re.sub(
158
+ r"^[ \t]+",
159
+ "",
160
+ formatted_text,
161
+ flags=re.MULTILINE,
162
+ )
163
+
164
+ return formatted_text.strip()
165
+
166
+
167
+ def infer(audio_input, progress=gr.Progress(track_tqdm=True)):
168
  progress(0.0, desc="Starting...")
169
 
170
+ # STEP 1 | Split vocals from the song/audio file
171
+ splt_result = split_process(
172
+ audio_input,
173
+ "vocals",
174
  progress=progress,
175
  )
176
 
177
+ print(splt_result)
178
+
179
+ # STEP 2 | Transcribe vocals
180
  progress(0.92, desc="Transcribing vocals with Whisper...")
181
+
182
+ whisper_result = transcribe(
183
+ splt_result,
184
+ "transcribe",
185
+ )
186
+
187
+ print(whisper_result)
188
+
189
+ # STEP 3 | Format lyrics
190
+ progress(0.98, desc="Formatting lyrics...")
191
+
192
+ lyrics = format_lyrics(whisper_result)
193
+
194
+ print(lyrics)
195
 
196
  progress(1.0, desc="Done.")
197
 
198
+ return splt_result, lyrics
199
 
200
 
201
  css = """
202
  #col-container {
203
+ max-width: 510px;
204
  margin-left: auto;
205
  margin-right: auto;
206
  }
 
 
 
 
 
207
  """
208
 
209
 
210
  with gr.Blocks() as demo:
211
  with gr.Column(elem_id="col-container"):
212
+ gr.HTML(
213
+ """
214
+ <div style="text-align: center; max-width: 700px; margin: 0 auto;">
215
+ <div
216
+ style="
217
+ display: inline-flex;
218
+ align-items: center;
219
+ gap: 0.8rem;
220
+ font-size: 1.75rem;
221
+ "
222
+ >
223
+ <h1 style="font-weight: 900; margin-bottom: 7px; margin-top: 5px;">
224
+ Song To Lyrics
225
+ </h1>
226
+ </div>
227
+ <p style="margin-bottom: 10px; font-size: 94%">
228
+ Send the audio file of your favorite song, and get the lyrics! <br />
229
+ Under the hood, we split and get the vocals track from the audio file, then send the vocals to Whisper.
230
+ </p>
231
+ </div>
232
  """
 
 
 
 
 
 
233
  )
234
 
235
  song_in = gr.Audio(
236
  label="Song input",
237
  type="numpy",
238
+ sources="upload",
239
  )
240
 
241
  getlyrics_btn = gr.Button("Get Lyrics!")
 
243
  vocals_out = gr.Audio(label="Vocals Only")
244
  lyrics_res = gr.Textbox(label="Lyrics")
245
 
246
+ getlyrics_btn.click(
247
+ fn=infer,
248
+ inputs=[song_in],
249
+ outputs=[vocals_out, lyrics_res],
250
+ )
251
 
252
 
253
  demo.queue().launch(css=css, ssr_mode=False)