MySafeCode's picture
Update app.py
f12c539 verified
import os
import requests
import gradio as gr
from dotenv import load_dotenv
import json
import uuid
import tempfile
from datetime import datetime
# Load environment variables from .env file
load_dotenv()
# Get Suno API key from environment variable (loaded from secrets)
SUNO_API_KEY = os.environ.get("SunoKey")
# Fixed callback URL
FIXED_CALLBACK_URL = "https://1hit.no/cover/cb.php"
# API endpoint
SUNO_API_URL = "https://api.sunoapi.org/api/v1/generate/upload-cover"
def generate_suno_music(
prompt,
title,
style,
upload_url_type,
custom_upload_url,
instrumental=True,
model="V4_5ALL",
persona_id="",
negative_tags="",
vocal_gender="m",
style_weight=0.65,
weirdness_constraint=0.65,
audio_weight=0.65,
custom_mode=True
):
"""
Generate music using Suno API with fixed callback URL
"""
# Check if API key is available
if not SUNO_API_KEY:
return f"Error: Suno API key not found. Please set the 'SunoKey' environment variable or secret."
# Determine upload URL based on selection
if upload_url_type == "auto":
# Generate a temporary upload URL (simulated - in practice this would be your storage service)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
unique_id = str(uuid.uuid4())[:8]
upload_url = f"https://storage.temp.example.com/uploads/{timestamp}_{unique_id}.mp3"
else:
# Use custom URL provided by user
upload_url = custom_upload_url.strip()
if not upload_url:
return "Error: Please provide a custom upload URL or select 'Auto-generate temporary URL'"
# Prepare payload with fixed callback URL
payload = {
"uploadUrl": upload_url,
"customMode": custom_mode,
"instrumental": instrumental,
"model": model,
"callBackUrl": FIXED_CALLBACK_URL, # Always use fixed callback URL
"prompt": prompt,
"style": style,
"title": title,
"personaId": persona_id,
"negativeTags": negative_tags,
"vocalGender": vocal_gender,
"styleWeight": style_weight,
"weirdnessConstraint": weirdness_constraint,
"audioWeight": audio_weight
}
# Remove empty fields
payload = {k: v for k, v in payload.items() if v not in ["", None]}
# Prepare headers
headers = {
"Authorization": f"Bearer {SUNO_API_KEY}",
"Content-Type": "application/json"
}
try:
# Make API request
response = requests.post(SUNO_API_URL, json=payload, headers=headers)
# Check response status
if response.status_code == 200:
result = response.json()
if result.get("code") == 200:
task_id = result.get("data", {}).get("taskId", "Unknown")
generated_url = upload_url if upload_url_type == "auto" else "Custom URL provided"
return f"""✅ Success!
Task ID: {task_id}
Upload URL: {generated_url}
Callback URL: {FIXED_CALLBACK_URL}
📋 Full API Response:
{json.dumps(result, indent=2)}"""
else:
return f"""❌ API Error: {result.get('msg', 'Unknown error')}
📋 Full API Response:
{json.dumps(result, indent=2)}"""
else:
return f"""❌ HTTP Error {response.status_code}
Response:
{response.text}"""
except requests.exceptions.RequestException as e:
return f"❌ Request failed: {str(e)}"
except json.JSONDecodeError as e:
return f"❌ Failed to parse response: {str(e)}\n\nResponse text: {response.text}"
except Exception as e:
return f"❌ Unexpected error: {str(e)}"
# Create Gradio interface
with gr.Blocks(title="Suno Music Generator") as app:
gr.Markdown("# 🎵 Suno Music Generator")
gr.Markdown(f"Generate music using Suno API. Callback URL is fixed to: `{FIXED_CALLBACK_URL}`")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### API Status")
api_status = gr.Textbox(
label="API Key Status",
value=f"API Key: {'✅ Loaded' if SUNO_API_KEY else '❌ Not found'}"
if SUNO_API_KEY else "❌ API Key not found. Please set 'SunoKey' environment variable.",
interactive=False
)
with gr.Column(scale=2):
gr.Markdown("### About")
gr.Markdown(f"""
This app generates music using the Suno API.
**Fixed Callback URL:** `{FIXED_CALLBACK_URL}`
**Required setup:**
1. The basis for song generation is an mp3 url.
2. The setup here is weird. You click the automatic - not working button.
3. Then the other button.
4. Add URL. Typically from suno, udio or soundcloud download from other libraries.
""")
with gr.Tabs():
with gr.TabItem("Basic Settings"):
with gr.Row():
with gr.Column():
prompt = gr.Textbox(
label="Music Prompt",
value="A calm and relaxing piano track with soft melodies",
placeholder="Describe the music you want to generate...",
lines=3
)
title = gr.Textbox(
label="Title",
value="Peaceful Piano Meditation",
placeholder="Title for your music track"
)
style = gr.Textbox(
label="Style",
value="Classical",
placeholder="Music style (e.g., Classical, Pop, Rock, Jazz)"
)
with gr.Column():
gr.Markdown("### Upload URL Settings")
upload_url_type = gr.Radio(
label="Upload URL Type",
choices=[
("Auto - not working", "auto"),
("Use custom URL", "custom")
],
value="custom",
info="Auto-generate creates a temporary URL, or provide your own"
)
custom_upload_url = gr.Textbox(
label="Custom Upload URL",
value="https://storage.example.com/upload",
placeholder="Enter your custom upload URL here",
visible=False
)
# Show/hide custom URL field based on radio selection
def toggle_upload_url(selection):
return gr.update(visible=selection == "custom")
upload_url_type.change(
toggle_upload_url,
inputs=upload_url_type,
outputs=custom_upload_url
)
with gr.TabItem("Advanced Settings"):
with gr.Row():
with gr.Column():
model = gr.Dropdown(
label="Model",
choices=["V5", "V4_5ALL", "V4", "V3", "V2"],
value="V4_5ALL"
)
instrumental = gr.Checkbox(
label="Instrumental",
value=True
)
custom_mode = gr.Checkbox(
label="Custom Mode",
value=True
)
with gr.Column():
persona_id = gr.Textbox(
label="Persona ID (Optional)",
value="persona_123",
placeholder="Leave empty for no persona"
)
negative_tags = gr.Textbox(
label="Negative Tags (Optional)",
value="Heavy Metal, Upbeat Drums",
placeholder="Tags to avoid in the music"
)
vocal_gender = gr.Dropdown(
label="Vocal Gender",
choices=["m", "f", "none"],
value="m"
)
with gr.TabItem("Weight Settings"):
with gr.Row():
with gr.Column():
style_weight = gr.Slider(
label="Style Weight",
minimum=0.0,
maximum=1.0,
value=0.65,
step=0.05
)
weirdness_constraint = gr.Slider(
label="Weirdness Constraint",
minimum=0.0,
maximum=1.0,
value=0.65,
step=0.05
)
audio_weight = gr.Slider(
label="Audio Weight",
minimum=0.0,
maximum=1.0,
value=0.65,
step=0.05
)
# Submit button
submit_btn = gr.Button("🎶 Generate Music", variant="primary", size="lg")
# Output
output = gr.Textbox(
label="Generation Result",
lines=12,
interactive=False
)
# Example button
example_btn = gr.Button("📋 Load Example", variant="secondary")
# Define button actions
def load_example():
return {
prompt: "A calm and relaxing piano track with soft melodies",
title: "Peaceful Piano Meditation",
style: "Classical",
upload_url_type: "auto",
custom_upload_url: "https://storage.example.com/upload",
model: "V4_5ALL",
instrumental: True,
custom_mode: True,
persona_id: "persona_123",
negative_tags: "Heavy Metal, Upbeat Drums",
vocal_gender: "m",
style_weight: 0.65,
weirdness_constraint: 0.65,
audio_weight: 0.65
}
# Connect buttons
example_btn.click(
load_example,
outputs=[
prompt, title, style, upload_url_type, custom_upload_url,
model, instrumental, custom_mode, persona_id,
negative_tags, vocal_gender, style_weight,
weirdness_constraint, audio_weight
]
)
submit_btn.click(
generate_suno_music,
inputs=[
prompt, title, style, upload_url_type, custom_upload_url,
instrumental, model, persona_id, negative_tags,
vocal_gender, style_weight, weirdness_constraint,
audio_weight, custom_mode
],
outputs=output
)
# Footer
gr.Markdown("---")
# Launch the app
if __name__ == "__main__":
# Check if API key is available
if not SUNO_API_KEY:
print("⚠️ Warning: Suno API key not found.")
print("Please set the 'SunoKey' environment variable:")
print(" - For Hugging Face Spaces: Add as Repository Secret")
print(" - For local development: Create a .env file with SunoKey=your_key")
print(" - Or set it directly: export SunoKey=your_key")
app.launch(
server_name="0.0.0.0" if os.environ.get("GRADIO_SERVER_NAME") else None,
server_port=int(os.environ.get("GRADIO_SERVER_PORT", 7860)),
share=os.environ.get("GRADIO_SHARE", "False").lower() == "true",
theme=gr.themes.Soft()
)