Surn commited on
Commit
1e4f3ac
·
1 Parent(s): 72852f7

Improve progress reporting for audio separation

Browse files

Refactored process_video_with_progress to handle structured progress updates using value and description, and updated separate_tracks to yield progress as dictionary events with normalized float values. Enhanced clarity and granularity of progress feedback throughout the audio separation workflow.

Files changed (2) hide show
  1. app.py +4 -3
  2. modules/yt_audio_get_tracks.py +19 -12
app.py CHANGED
@@ -199,7 +199,8 @@ def process_video_with_progress(
199
  status_lines = []
200
 
201
  def on_progress(message):
202
- status_lines.append(message)
 
203
 
204
  try:
205
  if cookies_upload is not None:
@@ -227,7 +228,7 @@ def process_video_with_progress(
227
  progress(0.4, desc="Separating tracks")
228
  yield "", "\n".join(status_lines)
229
 
230
- separation = separate_tracks(audio_path, job_id, progress_callback=on_progress)
231
  while True:
232
  try:
233
  event_type, payload = next(separation)
@@ -235,7 +236,7 @@ def process_video_with_progress(
235
  break
236
 
237
  if event_type == "progress":
238
- status_lines.append(str(payload))
239
  yield "", "\n".join(status_lines)
240
  elif event_type == "result":
241
  drums, vocals, guitar, bass, other, piano, music, full = payload
 
199
  status_lines = []
200
 
201
  def on_progress(message):
202
+ if isinstance(message, str):
203
+ status_lines.append(message)
204
 
205
  try:
206
  if cookies_upload is not None:
 
228
  progress(0.4, desc="Separating tracks")
229
  yield "", "\n".join(status_lines)
230
 
231
+ separation = separate_tracks(audio_path, job_id)
232
  while True:
233
  try:
234
  event_type, payload = next(separation)
 
236
  break
237
 
238
  if event_type == "progress":
239
+ progress(payload["value"], desc=payload["desc"])
240
  yield "", "\n".join(status_lines)
241
  elif event_type == "result":
242
  drums, vocals, guitar, bass, other, piano, music, full = payload
modules/yt_audio_get_tracks.py CHANGED
@@ -163,12 +163,13 @@ def separate_tracks(input_wav, job_id, progress_callback=None):
163
  if not os.path.exists(input_wav):
164
  raise FileNotFoundError(f"{input_wav} does not exist")
165
 
166
- def _emit(msg):
167
- _emit_progress(progress_callback, msg)
168
- return ("progress", msg)
 
169
 
170
- yield _emit("Validating input audio...")
171
- yield _emit("Starting Demucs separation (htdemucs_6s)...")
172
 
173
  output_dir = 'separated'
174
 
@@ -178,6 +179,7 @@ def separate_tracks(input_wav, job_id, progress_callback=None):
178
  ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1)
179
 
180
  progress_pattern = re.compile(r'(\d+)%\|')
 
181
 
182
  # Read progress in real time
183
  for line in proc.stdout or []:
@@ -186,15 +188,20 @@ def separate_tracks(input_wav, job_id, progress_callback=None):
186
  match = progress_pattern.search(line)
187
  if match:
188
  percent = int(match.group(1))
189
- yield _emit(f"Demucs progress: {percent}%")
 
 
 
 
 
190
  elif "Separating track" in line:
191
- yield _emit("Demucs: Starting separation...")
192
 
193
  proc.wait()
194
  if proc.returncode != 0:
195
  raise RuntimeError("Demucs failed")
196
 
197
- yield _emit("Demucs separation complete. Loading stems...")
198
 
199
  base = os.path.join(output_dir, 'htdemucs_6s', job_id)
200
 
@@ -205,20 +212,20 @@ def separate_tracks(input_wav, job_id, progress_callback=None):
205
  piano = f'{base}/piano.mp3'
206
  other = f'{base}/other.mp3'
207
 
208
- yield _emit("Creating music stem (bass + other)...")
209
  music = AudioSegment.from_mp3(bass).overlay(AudioSegment.from_mp3(other))
210
  music_path = os.path.join(base, 'music.mp3')
211
  music.export(music_path, format="mp3")
212
 
213
  # Full mix export (rest of your code)
214
  full_path = os.path.join(base, 'full.mp3')
215
- yield _emit("Exporting full mix...")
216
  src = AudioSegment.from_file(input_wav)
217
  src.export(full_path, format="mp3")
218
 
219
- yield _emit("Cleaning up...")
220
  os.remove(input_wav)
221
- yield _emit("Separation complete.")
222
 
223
  yield ("result", (drums, vocals, guitar, bass, other, piano, music_path, full_path))
224
 
 
163
  if not os.path.exists(input_wav):
164
  raise FileNotFoundError(f"{input_wav} does not exist")
165
 
166
+ def _emit_progress_event(value, desc):
167
+ if progress_callback is not None:
168
+ progress_callback(desc)
169
+ return ("progress", {"value": value, "desc": desc})
170
 
171
+ yield _emit_progress_event(0.0, "Validating input audio...")
172
+ yield _emit_progress_event(0.05, "Starting Demucs separation (htdemucs_6s)...")
173
 
174
  output_dir = 'separated'
175
 
 
179
  ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1)
180
 
181
  progress_pattern = re.compile(r'(\d+)%\|')
182
+ last_percent = None
183
 
184
  # Read progress in real time
185
  for line in proc.stdout or []:
 
188
  match = progress_pattern.search(line)
189
  if match:
190
  percent = int(match.group(1))
191
+ if percent != last_percent:
192
+ last_percent = percent
193
+ yield _emit_progress_event(
194
+ 0.1 + (percent / 100.0) * 0.7,
195
+ f"Demucs progress: {percent}%",
196
+ )
197
  elif "Separating track" in line:
198
+ yield _emit_progress_event(0.1, "Demucs: Starting separation...")
199
 
200
  proc.wait()
201
  if proc.returncode != 0:
202
  raise RuntimeError("Demucs failed")
203
 
204
+ yield _emit_progress_event(0.82, "Demucs separation complete. Loading stems...")
205
 
206
  base = os.path.join(output_dir, 'htdemucs_6s', job_id)
207
 
 
212
  piano = f'{base}/piano.mp3'
213
  other = f'{base}/other.mp3'
214
 
215
+ yield _emit_progress_event(0.88, "Creating music stem (bass + other)...")
216
  music = AudioSegment.from_mp3(bass).overlay(AudioSegment.from_mp3(other))
217
  music_path = os.path.join(base, 'music.mp3')
218
  music.export(music_path, format="mp3")
219
 
220
  # Full mix export (rest of your code)
221
  full_path = os.path.join(base, 'full.mp3')
222
+ yield _emit_progress_event(0.94, "Exporting full mix...")
223
  src = AudioSegment.from_file(input_wav)
224
  src.export(full_path, format="mp3")
225
 
226
+ yield _emit_progress_event(0.98, "Cleaning up...")
227
  os.remove(input_wav)
228
+ yield _emit_progress_event(1.0, "Separation complete.")
229
 
230
  yield ("result", (drums, vocals, guitar, bass, other, piano, music_path, full_path))
231