MySafeCode commited on
Commit
858e9bd
·
verified ·
1 Parent(s): 96290a4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -64
app.py CHANGED
@@ -9,23 +9,30 @@ SUNO_KEY = os.environ.get("SunoKey", "")
9
  if not SUNO_KEY:
10
  print("⚠️ SunoKey not set!")
11
 
12
- def generate_lyrics(prompt):
13
- """Final working lyrics generator"""
14
  if not SUNO_KEY:
15
  yield "❌ Error: SunoKey not configured in environment variables"
16
  return
17
 
18
- if not prompt.strip():
19
- yield "❌ Error: Please enter a prompt"
20
  return
21
 
22
- # Submit task
 
 
 
 
 
23
  try:
24
  resp = requests.post(
25
- "https://api.sunoapi.org/api/v1/lyrics",
26
  json={
27
- "prompt": prompt,
28
- "callBackUrl": "http://dummy.com/callback" # Required but not used
 
 
29
  },
30
  headers={
31
  "Authorization": f"Bearer {SUNO_KEY}",
@@ -43,18 +50,18 @@ def generate_lyrics(prompt):
43
  yield f"❌ API error: {data.get('msg', 'Unknown')}"
44
  return
45
 
46
- task_id = data["data"]["taskId"]
47
- yield f"✅ **Submitted!**\nTask ID: `{task_id}`\n\n⏳ Waiting for lyrics...\n"
48
 
49
  # Poll for results
50
- for attempt in range(30): # 30 attempts * 5 seconds = 150 seconds max
51
  time.sleep(5)
52
 
53
  try:
54
  check = requests.get(
55
- "https://api.sunoapi.org/api/v1/lyrics/record-info",
56
  headers={"Authorization": f"Bearer {SUNO_KEY}"},
57
- params={"taskId": task_id},
58
  timeout=30
59
  )
60
 
@@ -63,107 +70,151 @@ def generate_lyrics(prompt):
63
  status = check_data["data"].get("status", "PENDING")
64
 
65
  if status == "SUCCESS":
66
- # Success! Extract lyrics
67
- response_data = check_data["data"].get("response", {})
68
 
69
- if isinstance(response_data, str):
70
- # Sometimes response is a JSON string
71
- try:
72
- response_data = json.loads(response_data.replace('null', 'None'))
73
- except:
74
- response_data = {"data": []}
75
 
76
- lyrics_list = response_data.get("data", [])
 
77
 
78
- if lyrics_list:
79
- output = "🎵 **Lyrics Generated Successfully!**\n\n"
 
 
 
 
 
 
 
80
 
81
- for i, lyric in enumerate(lyrics_list, 1):
82
- title = lyric.get('title', f'Variant {i}')
83
- text = lyric.get('text', 'No lyrics')
84
-
85
- output += f"## Variant {i}: {title}\n"
86
- output += "```\n"
87
- output += text
88
- output += "\n```\n"
89
- output += "---\n\n"
 
 
 
 
 
 
 
90
 
91
- output += f"⏱️ Generated in about {(attempt + 1) * 5} seconds"
92
- yield output
93
- else:
94
- yield "✅ Completed but no lyrics found in response"
 
 
 
 
95
  return
96
 
97
  elif status == "FAILED":
98
  error = check_data["data"].get("errorMessage", "Unknown error")
99
- yield f"❌ Task failed: {error}"
100
  return
101
 
102
  else:
103
  # PENDING or PROCESSING
104
  yield (f"⏳ Status: {status}\n"
105
- f"Attempt: {attempt + 1}/30\n"
106
- f"Task ID: `{task_id}`\n\n"
107
- f"Still processing... (Usually takes 30-90 seconds)")
108
  else:
109
  yield f"⚠️ Check error: HTTP {check.status_code}"
110
 
111
  except Exception as e:
112
  yield f"⚠️ Error checking status: {str(e)}"
113
 
114
- yield "⏰ Timeout after 150 seconds. Try checking again later."
115
 
116
  except Exception as e:
117
  yield f"❌ Error: {str(e)}"
118
 
119
  # Create the app
120
- with gr.Blocks(title="Suno Lyrics Generator", theme="soft") as app:
121
- gr.Markdown("# 🎵 Suno Lyrics Generator")
122
- gr.Markdown("Generate song lyrics using Suno AI")
123
 
124
  with gr.Row():
125
  with gr.Column(scale=1):
126
- prompt = gr.Textbox(
127
- label="Lyrics Prompt",
128
- placeholder="Example: A happy song about sunshine and rainbows",
129
- lines=3
 
 
 
 
 
130
  )
131
- btn = gr.Button("🎵 Generate Lyrics", variant="primary", scale=1)
 
 
 
 
 
 
 
 
 
 
 
132
 
133
  gr.Markdown("""
134
  **How it works:**
135
- 1. Enter your lyrics idea
136
- 2. Click Generate
137
- 3. Wait 30-90 seconds
138
- 4. Get 2 lyric variants
 
139
 
140
- **Status messages:**
141
- - Submitted = Task accepted
142
- - PENDING/PROCESSING = Generating
143
- - 🎵 Success = Lyrics ready!
 
 
 
 
 
 
 
 
144
  """)
145
 
146
  with gr.Column(scale=2):
147
  output = gr.Markdown(
148
- label="Results",
149
- value="Your generated lyrics will appear here..."
150
  )
 
151
  gr.Markdown("---")
152
  gr.Markdown(
153
  """
154
  <div style="text-align: center; padding: 20px;">
155
  <p>Powered by <a href="https://suno.ai" target="_blank">Suno AI</a> •
156
  <a href="https://sunoapi.org" target="_blank">Suno API Docs</a> •
157
- <a href="https://github.com" target="_blank">GitHub</a></p>
158
- <p><small>This app uses the Suno API to generate AI-powered lyrics.</small></p>
 
159
  </div>
160
  """,
161
  elem_id="footer"
162
  )
163
 
164
- btn.click(generate_lyrics, prompt, output)
165
 
166
  if __name__ == "__main__":
167
- print("🚀 Starting Suno Lyrics Generator")
168
  print(f"🔑 SunoKey: {'✅ Set' if SUNO_KEY else '❌ Not set'}")
 
169
  app.launch(server_name="0.0.0.0", server_port=7860, share=False)
 
9
  if not SUNO_KEY:
10
  print("⚠️ SunoKey not set!")
11
 
12
+ def separate_vocals(task_id, audio_id, separation_type):
13
+ """Separate vocals and instruments from Suno tracks"""
14
  if not SUNO_KEY:
15
  yield "❌ Error: SunoKey not configured in environment variables"
16
  return
17
 
18
+ if not task_id.strip() or not audio_id.strip():
19
+ yield "❌ Error: Please enter both Task ID and Audio ID"
20
  return
21
 
22
+ # Validate separation type
23
+ if separation_type not in ["separate_vocal", "split_stem"]:
24
+ yield "❌ Error: Invalid separation type"
25
+ return
26
+
27
+ # Submit separation task
28
  try:
29
  resp = requests.post(
30
+ "https://api.sunoapi.org/api/v1/vocal-removal/generate",
31
  json={
32
+ "taskId": task_id,
33
+ "audioId": audio_id,
34
+ "type": separation_type,
35
+ "callBackUrl": "http://dummy.com/callback" # Required but not used for polling
36
  },
37
  headers={
38
  "Authorization": f"Bearer {SUNO_KEY}",
 
50
  yield f"❌ API error: {data.get('msg', 'Unknown')}"
51
  return
52
 
53
+ separation_task_id = data["data"]["taskId"]
54
+ yield f"✅ **Submitted!**\nSeparation Task ID: `{separation_task_id}`\n\n⏳ Processing separation...\n"
55
 
56
  # Poll for results
57
+ for attempt in range(40): # 40 attempts * 5 seconds = 200 seconds max
58
  time.sleep(5)
59
 
60
  try:
61
  check = requests.get(
62
+ "https://api.sunoapi.org/api/v1/vocal-removal/record-info",
63
  headers={"Authorization": f"Bearer {SUNO_KEY}"},
64
+ params={"taskId": separation_task_id},
65
  timeout=30
66
  )
67
 
 
70
  status = check_data["data"].get("status", "PENDING")
71
 
72
  if status == "SUCCESS":
73
+ # Success! Extract separation results
74
+ separation_info = check_data["data"].get("vocal_removal_info", {})
75
 
76
+ if not separation_info:
77
+ yield "✅ Completed but no separation results found"
78
+ return
 
 
 
79
 
80
+ # Format output based on separation type
81
+ output = "🎵 **Separation Complete!**\n\n"
82
 
83
+ if separation_type == "separate_vocal":
84
+ output += "## 2-Stem Separation\n\n"
85
+ output += f"**Vocals:** [Download]({separation_info.get('vocal_url', 'N/A')})\n"
86
+ output += f"**Instrumental:** [Download]({separation_info.get('instrumental_url', 'N/A')})\n"
87
+ if separation_info.get('origin_url'):
88
+ output += f"**Original:** [Download]({separation_info.get('origin_url')})\n"
89
+
90
+ elif separation_type == "split_stem":
91
+ output += "## 12-Stem Separation\n\n"
92
 
93
+ stems = [
94
+ ("Vocals", separation_info.get('vocal_url')),
95
+ ("Backing Vocals", separation_info.get('backing_vocals_url')),
96
+ ("Drums", separation_info.get('drums_url')),
97
+ ("Bass", separation_info.get('bass_url')),
98
+ ("Guitar", separation_info.get('guitar_url')),
99
+ ("Keyboard", separation_info.get('keyboard_url')),
100
+ ("Strings", separation_info.get('strings_url')),
101
+ ("Brass", separation_info.get('brass_url')),
102
+ ("Woodwinds", separation_info.get('woodwinds_url')),
103
+ ("Percussion", separation_info.get('percussion_url')),
104
+ ("Synth", separation_info.get('synth_url')),
105
+ ("FX/Other", separation_info.get('fx_url')),
106
+ ("Instrumental", separation_info.get('instrumental_url')),
107
+ ("Original", separation_info.get('origin_url'))
108
+ ]
109
 
110
+ for stem_name, stem_url in stems:
111
+ if stem_url:
112
+ output += f"**{stem_name}:** [Download]({stem_url})\n"
113
+
114
+ output += f"\n⏱️ Processed in about {(attempt + 1) * 5} seconds\n"
115
+ output += f"⚠️ **Note:** Download links expire in 14 days"
116
+
117
+ yield output
118
  return
119
 
120
  elif status == "FAILED":
121
  error = check_data["data"].get("errorMessage", "Unknown error")
122
+ yield f"❌ Separation failed: {error}"
123
  return
124
 
125
  else:
126
  # PENDING or PROCESSING
127
  yield (f"⏳ Status: {status}\n"
128
+ f"Attempt: {attempt + 1}/40\n"
129
+ f"Separation Task ID: `{separation_task_id}`\n\n"
130
+ f"Processing... (Usually takes 30-120 seconds)")
131
  else:
132
  yield f"⚠️ Check error: HTTP {check.status_code}"
133
 
134
  except Exception as e:
135
  yield f"⚠️ Error checking status: {str(e)}"
136
 
137
+ yield "⏰ Timeout after 200 seconds. Try checking again later."
138
 
139
  except Exception as e:
140
  yield f"❌ Error: {str(e)}"
141
 
142
  # Create the app
143
+ with gr.Blocks(title="Suno Stem Separator", theme="soft") as app:
144
+ gr.Markdown("# 🎵 Suno Stem Separator")
145
+ gr.Markdown("Separate Suno AI tracks into vocal and instrument stems")
146
 
147
  with gr.Row():
148
  with gr.Column(scale=1):
149
+ task_id = gr.Textbox(
150
+ label="Original Task ID",
151
+ placeholder="Example: 5c79****be8e",
152
+ info="The task ID from your Suno music generation"
153
+ )
154
+ audio_id = gr.Textbox(
155
+ label="Audio ID",
156
+ placeholder="Example: e231****-****-****-****-****8cadc7dc",
157
+ info="The specific audio ID to separate"
158
  )
159
+
160
+ separation_type = gr.Radio(
161
+ label="Separation Type",
162
+ choices=[
163
+ ("separate_vocal (2 stems - 1 credit)", "separate_vocal"),
164
+ ("split_stem (12 stems - 5 credits)", "split_stem")
165
+ ],
166
+ value="separate_vocal",
167
+ info="Choose separation mode"
168
+ )
169
+
170
+ btn = gr.Button("🎵 Separate Stems", variant="primary", scale=1)
171
 
172
  gr.Markdown("""
173
  **How it works:**
174
+ 1. Enter Task ID and Audio ID from your Suno track
175
+ 2. Choose separation type
176
+ 3. Click Separate Stems
177
+ 4. Wait 30-120 seconds
178
+ 5. Get download links for each stem
179
 
180
+ **Separation types:**
181
+ - 🎤 **separate_vocal**: Vocals + Instrumental (2 stems, 1 credit)
182
+ - 🎛️ **split_stem**: 12 detailed stems (5 credits)
183
+
184
+ **Stem Types in split_stem:**
185
+ - Vocals, Backing Vocals, Drums, Bass
186
+ - Guitar, Keyboard, Strings, Brass
187
+ - Woodwinds, Percussion, Synth, FX/Other
188
+
189
+ ⚠️ **Important:**
190
+ - Each request consumes credits
191
+ - Links expire in 14 days
192
  """)
193
 
194
  with gr.Column(scale=2):
195
  output = gr.Markdown(
196
+ label="Separation Results",
197
+ value="Your separated stems will appear here..."
198
  )
199
+
200
  gr.Markdown("---")
201
  gr.Markdown(
202
  """
203
  <div style="text-align: center; padding: 20px;">
204
  <p>Powered by <a href="https://suno.ai" target="_blank">Suno AI</a> •
205
  <a href="https://sunoapi.org" target="_blank">Suno API Docs</a> •
206
+ <a href="https://docs.sunoapi.org/separate-vocals" target="_blank">Stem Separation Guide</a></p>
207
+ <p><small>This app uses the Suno API to separate tracks into individual stems.</small></p>
208
+ <p><small>💡 <strong>Tip:</strong> Find your Task ID and Audio ID in your Suno generation history or API responses.</small></p>
209
  </div>
210
  """,
211
  elem_id="footer"
212
  )
213
 
214
+ btn.click(separate_vocals, [task_id, audio_id, separation_type], output)
215
 
216
  if __name__ == "__main__":
217
+ print("🚀 Starting Suno Stem Separator")
218
  print(f"🔑 SunoKey: {'✅ Set' if SUNO_KEY else '❌ Not set'}")
219
+ print("🌐 Open your browser to: http://localhost:7860")
220
  app.launch(server_name="0.0.0.0", server_port=7860, share=False)