MySafeCode commited on
Commit
a74cea0
·
verified ·
1 Parent(s): 5afb0f7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +152 -72
app.py CHANGED
@@ -3,14 +3,16 @@ import requests
3
  import os
4
  import time
5
  import json
 
6
 
7
  # Suno API key
8
  SUNO_KEY = os.environ.get("SunoKey", "")
9
  if not SUNO_KEY:
10
  print("⚠️ SunoKey not set!")
11
 
12
- # Store task info for auto-fill
13
  current_task_info = {}
 
14
 
15
  def get_audio_files(task_id):
16
  """Get audio files from Suno task ID"""
@@ -99,6 +101,8 @@ def submit_separation_task(task_id, audio_id, separation_type):
99
  current_task_info["original_task_id"] = task_id
100
  current_task_info["audio_id"] = audio_id
101
  current_task_info["separation_type"] = separation_type
 
 
102
 
103
  return f"✅ Task submitted!\n\n**Separation Task ID:** `{separation_task_id}`\n\n⏳ Starting auto-polling...", separation_task_id
104
  else:
@@ -184,8 +188,44 @@ def format_download_links(results, separation_task_id):
184
 
185
  return output
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  # Create the app
188
- with gr.Blocks(title="Suno Stem Separator", theme="soft") as app:
189
  gr.Markdown("# 🎵 Suno Stem Separator")
190
 
191
  with gr.Row():
@@ -241,6 +281,7 @@ with gr.Blocks(title="Suno Stem Separator", theme="soft") as app:
241
  interactive=False,
242
  visible=False
243
  )
 
244
 
245
  # Manual polling section
246
  with gr.Group():
@@ -265,8 +306,10 @@ with gr.Blocks(title="Suno Stem Separator", theme="soft") as app:
265
  elem_id="viewer_link"
266
  )
267
 
268
- # Store current separation task ID
269
  current_separation_task_id = gr.State(value="")
 
 
270
 
271
  # Step 1: Get audio files
272
  def on_get_audio(task_id):
@@ -287,27 +330,29 @@ with gr.Blocks(title="Suno Stem Separator", theme="soft") as app:
287
  )
288
 
289
  # Step 2-3: Submit separation task
290
- def on_submit(task_id, audio_id, sep_type):
291
  if not task_id or not audio_id:
292
- return "❌ Missing Task ID or Audio ID", None, gr.Markdown(), gr.Slider(visible=False)
293
 
294
  status, separation_task_id = submit_separation_task(task_id, audio_id, sep_type)
295
 
296
  if not separation_task_id:
297
- return status, None, gr.Markdown(), gr.Slider(visible=False)
298
 
299
  # Start auto-polling
300
  return (
301
  status,
302
  separation_task_id,
303
- gr.Markdown("⏳ Polling started..."),
304
- gr.Slider(visible=True, value=0)
 
 
305
  )
306
 
307
- # Auto-polling function
308
- def auto_poll(separation_task_id, attempt):
309
- if not separation_task_id:
310
- return "⏳ Waiting for task...", 0, gr.Markdown(), False
311
 
312
  attempt += 1
313
 
@@ -315,76 +360,58 @@ with gr.Blocks(title="Suno Stem Separator", theme="soft") as app:
315
  status, results, error = poll_separation_status(separation_task_id)
316
 
317
  if error:
318
- return f"❌ Poll error: {error}", attempt, gr.Markdown(), attempt >= 60
319
 
320
  if status == "SUCCESS":
321
  if results:
322
  output = f"✅ **Separation Complete!**\n\n"
323
  output += f"**Task ID:** `{separation_task_id}`\n\n"
324
  output += format_download_links(results, separation_task_id)
325
- return output, attempt, gr.Markdown(), True
326
  else:
327
  output = f"✅ **Processing Complete**\n\n"
328
  output += f"**Task ID:** `{separation_task_id}`\n\n"
329
  output += "Check callback results: "
330
  output += f"[Viewer](https://1hit.no/viewer.php?task_id={separation_task_id})"
331
- return output, attempt, gr.Markdown(), True
332
 
333
  elif status in ["PENDING", "PROCESSING", "RUNNING"]:
334
- output = f"⏳ **Status:** {status}\n\n"
335
- output += f"**Task ID:** `{separation_task_id}`\n"
336
- output += f"**Attempt:** {attempt}/60\n"
337
- output += f"**Estimated wait:** {attempt * 5} seconds\n\n"
338
- output += "Polling every 5 seconds..."
339
- return output, attempt, gr.Markdown(), attempt >= 60
 
 
 
 
 
 
 
340
 
341
  elif status == "FAILED":
342
- output = f"❌ **Separation Failed**\n\n"
343
- output += f"**Task ID:** `{separation_task_id}`\n"
344
- output += f"**Status:** {status}\n"
345
- return output, attempt, gr.Markdown(), True
346
 
347
  else:
348
- output = f"🔄 **Status:** {status}\n\n"
349
- output += f"**Task ID:** `{separation_task_id}`\n"
350
- output += f"**Attempt:** {attempt}/60\n"
351
- return output, attempt, gr.Markdown(), attempt >= 60
 
 
 
 
 
 
 
352
 
353
- # Manual polling function
354
- def manual_poll(task_id):
355
- if not task_id:
356
- return "❌ Enter Task ID"
357
-
358
- status, results, error = poll_separation_status(task_id)
359
-
360
- if error:
361
- return f"❌ Error: {error}"
362
-
363
- if status == "SUCCESS":
364
- if results:
365
- output = f"✅ **Complete!**\n\n"
366
- output += f"**Task ID:** `{task_id}`\n\n"
367
- output += format_download_links(results, task_id)
368
- else:
369
- output = f"✅ **Complete** (no direct links)\n\n"
370
- output += f"**Task ID:** `{task_id}`\n\n"
371
- output += f"Check: [Viewer](https://1hit.no/viewer.php?task_id={task_id})"
372
-
373
- elif status in ["PENDING", "PROCESSING", "RUNNING"]:
374
- output = f"⏳ **Status:** {status}\n\n"
375
- output += f"**Task ID:** `{task_id}`\n\n"
376
- output += "Still processing. Try again in 30 seconds."
377
-
378
- elif status == "FAILED":
379
- output = f"❌ **Failed**\n\n"
380
- output += f"**Task ID:** `{task_id}`\n"
381
- output += f"**Status:** {status}"
382
-
383
- else:
384
- output = f"🔄 **Status:** {status}\n\n"
385
- output += f"**Task ID:** `{task_id}`"
386
-
387
- return output
388
 
389
  # Connect events
390
  get_audio_btn.click(
@@ -393,23 +420,42 @@ with gr.Blocks(title="Suno Stem Separator", theme="soft") as app:
393
  outputs=[audio_status, audio_dropdown, separation_type, submit_btn, submission_output]
394
  )
395
 
 
396
  submit_btn.click(
397
  fn=on_submit,
398
- inputs=[original_task_id, audio_dropdown, separation_type],
399
- outputs=[submission_output, current_separation_task_id, auto_poll_status, auto_poll_progress]
400
- ).then(
401
- fn=auto_poll,
402
- inputs=[current_separation_task_id, auto_poll_progress],
403
- outputs=[auto_poll_status, auto_poll_progress, download_output, auto_poll_progress],
404
- every=5 # Poll every 5 seconds
405
  )
406
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  poll_btn.click(
408
  fn=manual_poll,
409
  inputs=[poll_task_id],
410
  outputs=[poll_output]
411
  )
412
 
 
 
 
 
 
 
 
413
  # Auto-fill poll field when separation task is submitted
414
  def update_poll_field(separation_task_id):
415
  if separation_task_id:
@@ -421,9 +467,43 @@ with gr.Blocks(title="Suno Stem Separator", theme="soft") as app:
421
  inputs=[current_separation_task_id],
422
  outputs=[poll_task_id]
423
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
 
 
425
  if __name__ == "__main__":
426
  print("🚀 Starting Suno Stem Separator")
427
  print(f"🔑 SunoKey: {'✅ Set' if SUNO_KEY else '❌ Not set'}")
428
  print("🌐 Open your browser to: http://localhost:7860")
429
- app.launch(server_name="0.0.0.0", server_port=7860, share=False)
 
 
 
 
 
 
 
 
 
3
  import os
4
  import time
5
  import json
6
+ import threading
7
 
8
  # Suno API key
9
  SUNO_KEY = os.environ.get("SunoKey", "")
10
  if not SUNO_KEY:
11
  print("⚠️ SunoKey not set!")
12
 
13
+ # Store task info for auto-fill and polling
14
  current_task_info = {}
15
+ polling_active = {}
16
 
17
  def get_audio_files(task_id):
18
  """Get audio files from Suno task ID"""
 
101
  current_task_info["original_task_id"] = task_id
102
  current_task_info["audio_id"] = audio_id
103
  current_task_info["separation_type"] = separation_type
104
+ current_task_info["start_time"] = time.time()
105
+ current_task_info["attempt"] = 0
106
 
107
  return f"✅ Task submitted!\n\n**Separation Task ID:** `{separation_task_id}`\n\n⏳ Starting auto-polling...", separation_task_id
108
  else:
 
188
 
189
  return output
190
 
191
+ # Manual polling function
192
+ def manual_poll(task_id):
193
+ if not task_id:
194
+ return "❌ Enter Task ID"
195
+
196
+ status, results, error = poll_separation_status(task_id)
197
+
198
+ if error:
199
+ return f"❌ Error: {error}"
200
+
201
+ if status == "SUCCESS":
202
+ if results:
203
+ output = f"✅ **Complete!**\n\n"
204
+ output += f"**Task ID:** `{task_id}`\n\n"
205
+ output += format_download_links(results, task_id)
206
+ else:
207
+ output = f"✅ **Complete** (no direct links)\n\n"
208
+ output += f"**Task ID:** `{task_id}`\n\n"
209
+ output += f"Check: [Viewer](https://1hit.no/viewer.php?task_id={task_id})"
210
+
211
+ elif status in ["PENDING", "PROCESSING", "RUNNING"]:
212
+ output = f"⏳ **Status:** {status}\n\n"
213
+ output += f"**Task ID:** `{task_id}`\n\n"
214
+ output += "Still processing. Try again in 30 seconds."
215
+
216
+ elif status == "FAILED":
217
+ output = f"❌ **Failed**\n\n"
218
+ output += f"**Task ID:** `{task_id}`\n"
219
+ output += f"**Status:** {status}"
220
+
221
+ else:
222
+ output = f"🔄 **Status:** {status}\n\n"
223
+ output += f"**Task ID:** `{task_id}`"
224
+
225
+ return output
226
+
227
  # Create the app
228
+ with gr.Blocks() as app:
229
  gr.Markdown("# 🎵 Suno Stem Separator")
230
 
231
  with gr.Row():
 
281
  interactive=False,
282
  visible=False
283
  )
284
+ stop_poll_btn = gr.Button("⏹️ Stop Auto-Polling", variant="stop", visible=False)
285
 
286
  # Manual polling section
287
  with gr.Group():
 
306
  elem_id="viewer_link"
307
  )
308
 
309
+ # Store current separation task ID for auto-polling
310
  current_separation_task_id = gr.State(value="")
311
+ polling_active_flag = gr.State(value=False)
312
+ polling_thread = None
313
 
314
  # Step 1: Get audio files
315
  def on_get_audio(task_id):
 
330
  )
331
 
332
  # Step 2-3: Submit separation task
333
+ def on_submit(task_id, audio_id, sep_type, active_flag):
334
  if not task_id or not audio_id:
335
+ return "❌ Missing Task ID or Audio ID", "", "⏳ Waiting...", gr.Slider(visible=False), gr.Button(visible=False), active_flag
336
 
337
  status, separation_task_id = submit_separation_task(task_id, audio_id, sep_type)
338
 
339
  if not separation_task_id:
340
+ return status, "", "⏳ Waiting...", gr.Slider(visible=False), gr.Button(visible=False), active_flag
341
 
342
  # Start auto-polling
343
  return (
344
  status,
345
  separation_task_id,
346
+ "⏳ Polling started... (attempt 0/60)",
347
+ gr.Slider(visible=True, value=0),
348
+ gr.Button(visible=True),
349
+ True # Set polling active
350
  )
351
 
352
+ # Auto-polling update function
353
+ def update_auto_poll(separation_task_id, attempt, active_flag):
354
+ if not active_flag or not separation_task_id:
355
+ return "⏳ Polling stopped", attempt, "", False
356
 
357
  attempt += 1
358
 
 
360
  status, results, error = poll_separation_status(separation_task_id)
361
 
362
  if error:
363
+ return f"❌ Poll error: {error}", attempt, "", False
364
 
365
  if status == "SUCCESS":
366
  if results:
367
  output = f"✅ **Separation Complete!**\n\n"
368
  output += f"**Task ID:** `{separation_task_id}`\n\n"
369
  output += format_download_links(results, separation_task_id)
370
+ return f"✅ Complete! (attempt {attempt})", attempt, output, False
371
  else:
372
  output = f"✅ **Processing Complete**\n\n"
373
  output += f"**Task ID:** `{separation_task_id}`\n\n"
374
  output += "Check callback results: "
375
  output += f"[Viewer](https://1hit.no/viewer.php?task_id={separation_task_id})"
376
+ return f"✅ Complete! (attempt {attempt})", attempt, output, False
377
 
378
  elif status in ["PENDING", "PROCESSING", "RUNNING"]:
379
+ status_text = f"⏳ **Status:** {status}\n\n"
380
+ status_text += f"**Task ID:** `{separation_task_id}`\n"
381
+ status_text += f"**Attempt:** {attempt}/60\n"
382
+ status_text += f"**Elapsed:** {attempt * 5} seconds\n\n"
383
+ status_text += "Polling every 5 seconds..."
384
+
385
+ if attempt >= 60:
386
+ status_text = f"⏰ **Timeout after 5 minutes**\n\n"
387
+ status_text += f"**Task ID:** `{separation_task_id}`\n"
388
+ status_text += "Check manually or wait for callback."
389
+ return status_text, attempt, "", False
390
+
391
+ return status_text, attempt, "", True
392
 
393
  elif status == "FAILED":
394
+ status_text = f"❌ **Separation Failed**\n\n"
395
+ status_text += f"**Task ID:** `{separation_task_id}`\n"
396
+ status_text += f"**Status:** {status}"
397
+ return status_text, attempt, "", False
398
 
399
  else:
400
+ status_text = f"🔄 **Status:** {status}\n\n"
401
+ status_text += f"**Task ID:** `{separation_task_id}`\n"
402
+ status_text += f"**Attempt:** {attempt}/60"
403
+
404
+ if attempt >= 60:
405
+ status_text = f"⏰ **Timeout after 5 minutes**\n\n"
406
+ status_text += f"**Task ID:** `{separation_task_id}`\n"
407
+ status_text += "Check manually or wait for callback."
408
+ return status_text, attempt, "", False
409
+
410
+ return status_text, attempt, "", True
411
 
412
+ # Stop polling function
413
+ def stop_polling(active_flag):
414
+ return "⏹️ Polling stopped", 0, "", False, gr.Button(visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
 
416
  # Connect events
417
  get_audio_btn.click(
 
420
  outputs=[audio_status, audio_dropdown, separation_type, submit_btn, submission_output]
421
  )
422
 
423
+ # Submit button starts polling
424
  submit_btn.click(
425
  fn=on_submit,
426
+ inputs=[original_task_id, audio_dropdown, separation_type, polling_active_flag],
427
+ outputs=[submission_output, current_separation_task_id, auto_poll_status, auto_poll_progress, stop_poll_btn, polling_active_flag]
 
 
 
 
 
428
  )
429
 
430
+ # Create a separate function for polling that runs independently
431
+ def start_polling_thread(separation_task_id, attempt, active_flag):
432
+ """Background polling thread"""
433
+ while active_flag and attempt < 60:
434
+ time.sleep(5)
435
+ attempt += 1
436
+
437
+ status, results, error = poll_separation_status(separation_task_id)
438
+
439
+ if status == "SUCCESS" or status == "FAILED" or error:
440
+ # Update UI via queue or state
441
+ break
442
+
443
+ return attempt
444
+
445
+ # Manual polling
446
  poll_btn.click(
447
  fn=manual_poll,
448
  inputs=[poll_task_id],
449
  outputs=[poll_output]
450
  )
451
 
452
+ # Stop polling button
453
+ stop_poll_btn.click(
454
+ fn=stop_polling,
455
+ inputs=[polling_active_flag],
456
+ outputs=[auto_poll_status, auto_poll_progress, download_output, polling_active_flag, stop_poll_btn]
457
+ )
458
+
459
  # Auto-fill poll field when separation task is submitted
460
  def update_poll_field(separation_task_id):
461
  if separation_task_id:
 
467
  inputs=[current_separation_task_id],
468
  outputs=[poll_task_id]
469
  )
470
+
471
+ # Simple polling timer (manual refresh)
472
+ def manual_refresh(separation_task_id, attempt, active_flag):
473
+ if active_flag and separation_task_id:
474
+ return update_auto_poll(separation_task_id, attempt, active_flag)
475
+ return "⏳ Waiting for task...", 0, "", active_flag
476
+
477
+ # Add a refresh button for manual polling updates
478
+ refresh_btn = gr.Button("🔄 Refresh Status", variant="secondary", visible=False)
479
+
480
+ # Show/hide refresh button based on polling state
481
+ def toggle_refresh_button(active_flag):
482
+ return gr.Button(visible=active_flag)
483
+
484
+ polling_active_flag.change(
485
+ fn=toggle_refresh_button,
486
+ inputs=[polling_active_flag],
487
+ outputs=[refresh_btn]
488
+ )
489
+
490
+ refresh_btn.click(
491
+ fn=manual_refresh,
492
+ inputs=[current_separation_task_id, auto_poll_progress, polling_active_flag],
493
+ outputs=[auto_poll_status, auto_poll_progress, download_output, polling_active_flag]
494
+ )
495
 
496
+ # Launch the app
497
  if __name__ == "__main__":
498
  print("🚀 Starting Suno Stem Separator")
499
  print(f"🔑 SunoKey: {'✅ Set' if SUNO_KEY else '❌ Not set'}")
500
  print("🌐 Open your browser to: http://localhost:7860")
501
+
502
+ # Launch with theme parameter in launch() method
503
+ app.launch(
504
+ server_name="0.0.0.0",
505
+ server_port=7860,
506
+ share=False,
507
+ title="Suno Stem Separator",
508
+ theme="soft"
509
+ )