SUNO-API / app2.py
MySafeCode's picture
Update app2.py
b3861f7 verified
import gradio as gr
import requests
import os
import time
import json
from bs4 import BeautifulSoup
# Suno API key
SUNO_KEY = os.environ.get("SunoKey", "")
if not SUNO_KEY:
print("⚠️ SunoKey not set!")
# Function to fetch statistics from 1hit.no/log.php
def fetch_statistics():
"""Fetch statistics from 1hit.no/log.php"""
try:
# Fetch the log.php page
response = requests.get('https://1hit.no/log.php', timeout=10)
response.raise_for_status()
# Parse HTML
soup = BeautifulSoup(response.text, 'html.parser')
# Find all stat-number elements
stat_numbers = soup.find_all('span', class_='stat-number')
# Find all stat-label elements
stat_labels = soup.find_all('span', class_='stat-label')
# Take first 3 of each (or as many as available)
stats = []
#for i in range(min(3, len(stat_numbers), len(stat_labels))):
for i in [0, 2]: # Only get first (0) and third (2), skip middle (1)
number = stat_numbers[i].text.strip()
label = stat_labels[i].text.strip()
stats.append((number, label))
return stats
except Exception as e:
print(f"Error fetching statistics: {e}")
# Return default/fallback stats
return [
("N/A", "Lyrics Files"),
("N/A", "Total Lines"),
("N/A", "Unique Words")
]
def generate_lyrics(prompt):
"""Final working lyrics generator"""
if not SUNO_KEY:
yield "❌ Error: SunoKey not configured in environment variables"
return
if not prompt.strip():
yield "❌ Error: Please enter a prompt"
return
# Submit task
try:
resp = requests.post(
"https://api.sunoapi.org/api/v1/lyrics",
json={
"prompt": prompt,
"callBackUrl": "https://1hit.no/txtcallback.php" # Required
},
headers={
"Authorization": f"Bearer {SUNO_KEY}",
"Content-Type": "application/json"
},
timeout=30
)
if resp.status_code != 200:
yield f"❌ Submission failed: HTTP {resp.status_code}"
return
data = resp.json()
if data.get("code") != 200:
yield f"❌ API error: {data.get('msg', 'Unknown')}"
return
task_id = data["data"]["taskId"]
yield f"✅ **Submitted!**\nTask ID: `{task_id}`\n\n⏳ Waiting for lyrics...\n"
# Poll for results
for attempt in range(30): # 30 attempts * 5 seconds = 150 seconds max
time.sleep(5)
try:
check = requests.get(
"https://api.sunoapi.org/api/v1/lyrics/record-info",
headers={"Authorization": f"Bearer {SUNO_KEY}"},
params={"taskId": task_id},
timeout=30
)
if check.status_code == 200:
check_data = check.json()
status = check_data["data"].get("status", "PENDING")
if status == "SUCCESS":
# Success! Extract lyrics
response_data = check_data["data"].get("response", {})
if isinstance(response_data, str):
# Sometimes response is a JSON string
try:
response_data = json.loads(response_data.replace('null', 'None'))
except:
response_data = {"data": []}
lyrics_list = response_data.get("data", [])
if lyrics_list:
output = "🎵 **Lyrics Generated Successfully!**\n\n"
for i, lyric in enumerate(lyrics_list, 1):
title = lyric.get('title', f'Variant {i}')
text = lyric.get('text', 'No lyrics')
output += f"## Variant {i}: {title}\n"
output += "```\n"
output += text
output += "\n```\n"
output += "---\n\n"
output += f"⏱️ Generated in about {(attempt + 1) * 5} seconds"
yield output
else:
yield "✅ Completed but no lyrics found in response"
return
elif status == "FAILED":
error = check_data["data"].get("errorMessage", "Unknown error")
yield f"❌ Task failed: {error}"
return
else:
# PENDING or PROCESSING
yield (f"⏳ Status: {status}\n"
f"Attempt: {attempt + 1}/30\n"
f"Task ID: `{task_id}`\n\n"
f"Still processing... (Usually takes 30-90 seconds)")
else:
yield f"⚠️ Check error: HTTP {check.status_code}"
except Exception as e:
yield f"⚠️ Error checking status: {str(e)}"
yield "⏰ Timeout after 150 seconds. Try checking again later."
except Exception as e:
yield f"❌ Error: {str(e)}"
# Create the app
with gr.Blocks(title="Suno Lyrics Generator", theme="soft") as app:
# Fetch statistics
stats = fetch_statistics()
gr.Markdown("# 🎵 Suno Lyrics Generator")
gr.Markdown("Generate song lyrics using Suno AI")
# Statistics display at the top
gr.Markdown("## 📊 Live Statistics")
# Create a row for stats
with gr.Row():
for i, (number, label) in enumerate(stats):
with gr.Column():
gr.Markdown(f"""
<div style="
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 20px;
border-radius: 10px;
text-align: center;
color: white;
margin: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
">
<div style="font-size: 2.5em; font-weight: bold; margin-bottom: 10px;">
{number}
</div>
<div style="font-size: 1.2em;">
{label}
</div>
</div>
""")
gr.Markdown("---")
gr.Markdown("All songs are logged and public on 1hit.no (from 27th December 2025) and Suno AI")
gr.Markdown("""<a href="https://1hit.no/log.php" target="_blank" style="color: #667eea; text-decoration: none; font-weight: bold;">📊 View Detailed Song Log</a>""")
with gr.Row():
with gr.Column(scale=1):
prompt = gr.Textbox(
label="Lyrics Prompt",
placeholder="Example: A happy song about sunshine and rainbows",
lines=3
)
btn = gr.Button("🎵 Generate Lyrics", variant="primary", scale=1)
gr.Markdown("""
**How it works:**
1. Enter your lyrics idea
2. Click Generate
3. Wait 30-90 seconds
4. Get 2 lyric variants
**Status messages:**
- ✅ Submitted = Task accepted
- ⏳ PENDING/PROCESSING = Generating
- 🎵 Success = Lyrics ready!
""")
with gr.Column(scale=2):
output = gr.Markdown(
label="Results",
value="Your generated lyrics will appear here..."
)
gr.Markdown("---")
gr.Markdown(
"""
<div style="text-align: center; padding: 20px;">
<p>Powered by <a href="https://suno.com/invite/@espenvh" target="_blank">Suno AI</a> •
<a href="https://sunoapi.org" target="_blank">Suno API Docs</a> •
<a href="https://github.com" target="_blank">GitHub</a></p>
<p><small>This app uses the Suno API to generate AI-powered lyrics.</small></p>
</div>
""",
elem_id="footer"
)
btn.click(generate_lyrics, prompt, output)
if __name__ == "__main__":
print("🚀 Starting Suno Lyrics Generator")
print(f"🔑 SunoKey: {'✅ Set' if SUNO_KEY else '❌ Not set'}")
print("📊 Fetching statistics from 1hit.no/log.php...")
app.launch(server_name="0.0.0.0", server_port=7860, share=False)