Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -13,7 +13,8 @@ if not SUNO_KEY:
|
|
| 13 |
def generate_song_from_text(lyrics_text, style, title, instrumental, model, custom_mode=True):
|
| 14 |
"""Generate a song from lyrics text"""
|
| 15 |
if not SUNO_KEY:
|
| 16 |
-
|
|
|
|
| 17 |
|
| 18 |
if not lyrics_text.strip():
|
| 19 |
return "❌ Error: Please provide lyrics"
|
|
@@ -100,25 +101,42 @@ def generate_song_from_text(lyrics_text, style, title, instrumental, model, cust
|
|
| 100 |
task_id = data["data"]["taskId"]
|
| 101 |
yield f"✅ **Request submitted!**\nTask ID: `{task_id}`\n\n⏳ Waiting for song generation...\n"
|
| 102 |
|
| 103 |
-
# Poll for results
|
| 104 |
for attempt in range(60): # 60 attempts * 5 seconds = 300 seconds max (5 minutes)
|
| 105 |
time.sleep(5)
|
| 106 |
|
| 107 |
try:
|
|
|
|
| 108 |
check = requests.get(
|
| 109 |
-
"https://api.sunoapi.org/api/v1/
|
| 110 |
headers={"Authorization": f"Bearer {SUNO_KEY}"},
|
| 111 |
-
params={"taskId": task_id},
|
| 112 |
timeout=30
|
| 113 |
)
|
| 114 |
|
| 115 |
if check.status_code == 200:
|
| 116 |
check_data = check.json()
|
| 117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
|
| 119 |
if status == "COMPLETE":
|
| 120 |
# Success! Extract song URLs
|
| 121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
if songs:
|
| 123 |
output = "🎶 **Song Generation Complete!**\n\n"
|
| 124 |
for i, song in enumerate(songs, 1):
|
|
@@ -148,12 +166,12 @@ def generate_song_from_text(lyrics_text, style, title, instrumental, model, cust
|
|
| 148 |
return
|
| 149 |
|
| 150 |
elif status == "FAILED":
|
| 151 |
-
error =
|
| 152 |
yield f"❌ Task failed: {error}"
|
| 153 |
return
|
| 154 |
|
| 155 |
else:
|
| 156 |
-
# Still processing
|
| 157 |
if attempt % 6 == 0: # Update every 30 seconds
|
| 158 |
yield f"⏳ Status: {status}\nAttempt: {attempt + 1}/60\nTask ID: `{task_id}`\n\nStill processing... (Usually takes 30-180 seconds)\n\nTypical timing:\n- 30-40s: Stream URL ready\n- 2-3 min: Download URL ready"
|
| 159 |
else:
|
|
@@ -197,7 +215,7 @@ def upload_text_file(file):
|
|
| 197 |
|
| 198 |
def clear_all():
|
| 199 |
"""Clear all input fields"""
|
| 200 |
-
return "", "", "Generated Song", False, "V4_5ALL", ""
|
| 201 |
|
| 202 |
# Create the app
|
| 203 |
with gr.Blocks(title="Suno Song Generator", theme="soft") as app:
|
|
@@ -328,7 +346,7 @@ with gr.Blocks(title="Suno Song Generator", theme="soft") as app:
|
|
| 328 |
inputs=lyrics_text,
|
| 329 |
outputs=file_output
|
| 330 |
).then(
|
| 331 |
-
lambda: "💾 **Lyrics ready for download
|
| 332 |
outputs=output
|
| 333 |
)
|
| 334 |
|
|
|
|
| 13 |
def generate_song_from_text(lyrics_text, style, title, instrumental, model, custom_mode=True):
|
| 14 |
"""Generate a song from lyrics text"""
|
| 15 |
if not SUNO_KEY:
|
| 16 |
+
yield "❌ Error: SunoKey not configured in environment variables"
|
| 17 |
+
return
|
| 18 |
|
| 19 |
if not lyrics_text.strip():
|
| 20 |
return "❌ Error: Please provide lyrics"
|
|
|
|
| 101 |
task_id = data["data"]["taskId"]
|
| 102 |
yield f"✅ **Request submitted!**\nTask ID: `{task_id}`\n\n⏳ Waiting for song generation...\n"
|
| 103 |
|
| 104 |
+
# Poll for results - FIXED ENDPOINT
|
| 105 |
for attempt in range(60): # 60 attempts * 5 seconds = 300 seconds max (5 minutes)
|
| 106 |
time.sleep(5)
|
| 107 |
|
| 108 |
try:
|
| 109 |
+
# FIX: Use the correct endpoint from the API docs
|
| 110 |
check = requests.get(
|
| 111 |
+
f"https://api.sunoapi.org/api/v1/generate/record-info?taskId={task_id}",
|
| 112 |
headers={"Authorization": f"Bearer {SUNO_KEY}"},
|
|
|
|
| 113 |
timeout=30
|
| 114 |
)
|
| 115 |
|
| 116 |
if check.status_code == 200:
|
| 117 |
check_data = check.json()
|
| 118 |
+
|
| 119 |
+
# Check if the response structure is valid
|
| 120 |
+
if check_data.get("code") != 200:
|
| 121 |
+
yield f"⚠️ API returned error: {check_data.get('msg', 'Unknown')}"
|
| 122 |
+
continue
|
| 123 |
+
|
| 124 |
+
data_info = check_data.get("data", {})
|
| 125 |
+
status = data_info.get("status", "PENDING")
|
| 126 |
|
| 127 |
if status == "COMPLETE":
|
| 128 |
# Success! Extract song URLs
|
| 129 |
+
response_data = data_info.get("response", {})
|
| 130 |
+
|
| 131 |
+
# Try to parse response if it's a string
|
| 132 |
+
if isinstance(response_data, str):
|
| 133 |
+
try:
|
| 134 |
+
response_data = json.loads(response_data)
|
| 135 |
+
except:
|
| 136 |
+
response_data = {}
|
| 137 |
+
|
| 138 |
+
songs = response_data.get("data", [])
|
| 139 |
+
|
| 140 |
if songs:
|
| 141 |
output = "🎶 **Song Generation Complete!**\n\n"
|
| 142 |
for i, song in enumerate(songs, 1):
|
|
|
|
| 166 |
return
|
| 167 |
|
| 168 |
elif status == "FAILED":
|
| 169 |
+
error = data_info.get("errorMessage", "Unknown error")
|
| 170 |
yield f"❌ Task failed: {error}"
|
| 171 |
return
|
| 172 |
|
| 173 |
else:
|
| 174 |
+
# Still processing (PENDING or PROCESSING)
|
| 175 |
if attempt % 6 == 0: # Update every 30 seconds
|
| 176 |
yield f"⏳ Status: {status}\nAttempt: {attempt + 1}/60\nTask ID: `{task_id}`\n\nStill processing... (Usually takes 30-180 seconds)\n\nTypical timing:\n- 30-40s: Stream URL ready\n- 2-3 min: Download URL ready"
|
| 177 |
else:
|
|
|
|
| 215 |
|
| 216 |
def clear_all():
|
| 217 |
"""Clear all input fields"""
|
| 218 |
+
return "", "", "Generated Song", False, "V4_5ALL", "### Ready to generate!\n\n1. Enter lyrics\n2. Set style and title\n3. Click 'Generate Song'"
|
| 219 |
|
| 220 |
# Create the app
|
| 221 |
with gr.Blocks(title="Suno Song Generator", theme="soft") as app:
|
|
|
|
| 346 |
inputs=lyrics_text,
|
| 347 |
outputs=file_output
|
| 348 |
).then(
|
| 349 |
+
lambda: "💾 **Lyrics ready for download!**\n\nCheck the download button below.",
|
| 350 |
outputs=output
|
| 351 |
)
|
| 352 |
|