import streamlit as st import requests import json import os from datetime import datetime # Page configuration st.set_page_config( page_title="๐ŸŽต Suno AI Audio Generator", page_icon="๐ŸŽต", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS st.markdown(""" """, unsafe_allow_html=True) # Main App def main(): # Header st.title("๐ŸŽต Suno AI Audio Generator") st.markdown("Generate audio using Suno API with secure secret management") # Initialize session state if 'secrets_loaded' not in st.session_state: st.session_state.secrets_loaded = False st.session_state.suno_api_key = None st.session_state.callback_url = None st.session_state.last_api_response = None # Sidebar for configuration with st.sidebar: st.header("โš™๏ธ Configuration") st.markdown("---") # Secret Loading Section st.subheader("๐Ÿ” Load Secrets") # Load secrets from environment variables suno_api_key = st.secrets.get("SUNO_API_KEY", "").strip() or os.environ.get("SUNO_API_KEY", "") callback_url = st.secrets.get("CALLBACK_URL", "").strip() or os.environ.get("CALLBACK_URL", "") # Show loaded secrets status if suno_api_key and callback_url: st.success("Secrets loaded!") # Display masked secrets with st.expander("๐Ÿ” Loaded Secrets", expanded=True): st.markdown(f""" **API Key Status:** โœ… Loaded **Callback URL:** โœ… Loaded **Usage:** API calls will automatically use these secrets. """) st.session_state.suno_api_key = suno_api_key st.session_state.callback_url = callback_url st.session_state.secrets_loaded = True else: st.warning("Secrets not configured") st.markdown(""" **To configure:** 1. Set **SUNO_API_KEY** in `.streamlit/secrets.toml` 2. Set **CALLBACK_URL** in `.streamlit/secrets.toml` """) st.markdown("---") # Manual input for testing st.subheader("๐Ÿ”ง Manual Override (Testing)") manual_api_key = st.text_input("Enter API Key:", type="password") manual_callback_url = st.text_input("Enter Callback URL:", value=callback_url if callback_url else "") if st.button("๐Ÿ”ง Use Manual Credentials"): if manual_api_key and manual_callback_url: st.session_state.suno_api_key = manual_api_key st.session_state.callback_url = manual_callback_url st.session_state.secrets_loaded = True st.success("Using manual credentials") st.rerun() # Main content area col1, col2 = st[3, 1] with col1: st.markdown("### ๐ŸŽ›๏ธ API Parameters") # Task ID input task_id = st.text_input( "Task ID", value="5c79****be8e", help="Enter your Suno API task ID" ) # Audio ID input audio_id = st.text_input( "Audio ID", value="e231****-****-****-****-****8cadc7dc", help="Enter your Suno API audio ID" ) # API Endpoint selection endpoint = st.selectbox( "API Endpoint", options=["/api/v1/wav/generate", "/api/v1/audio/sync", "/api/v1/audio/status"], help="Select the Suno API endpoint to use" ) # Advanced options with st.expander("๐Ÿ”ง Advanced Options"): timeout = st.number_input("Timeout (seconds)", min_value=5, max_value=60, value=30, step=5) retry_count = st.slider("Retry Count", 0, 3, 1) show_debug = st.checkbox("Show Debug Info") with col2: st.markdown("### ๐Ÿ“Š Quick Actions") if st.button("๐Ÿš€ Test API Connection"): test_api_connection() if st.button("๐Ÿงช Test with Sample Data"): test_with_sample_data() if st.button("๐Ÿ“‹ Copy Configuration"): copy_configuration() # API Call Section st.markdown("---") st.markdown("### ๐Ÿš€ Make API Call") # Make API call button if st.button("๐ŸŽต Generate Audio", key="generate_audio", type="primary", use_container_width=True): make_api_call(task_id, audio_id, st.secrets.get("SUNO_API_KEY", manual_api_key if manual_api_key else suno_api_key), callback_url if callback_url else manual_callback_url) # Results section st.markdown("---") if 'last_api_response' in st.session_state: st.markdown("### ๐Ÿ“‹ Last API Response") st.json(st.session_state.last_api_response) # Download JSON button st.download_button( label="๐Ÿ“ฅ Download Response JSON", data=json.dumps(st.session_state.last_api_response, indent=2), file_name=f"suno_response_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json", mime="application/json" ) # Test API Connection def test_api_connection(): with st.spinner("Testing API connection..."): # Implement API connection test try: test_response = {"status": "connected"} st.success("โœ… API connection successful!") st.json(test_response) except Exception as e: st.error(f"โŒ API connection failed: {str(e)}") # Test with Sample Data def test_with_sample_data(): sample_data = { "taskId": "5c79****be8e", "audioId": "e231****-****-****-****-****8cadc7dc", "callBackUrl": st.session_state.callback_url } st.info("๐Ÿงช Testing with sample data...") st.json(sample_data) # Copy Configuration def copy_configuration(): config = { "api_key": st.session_state.suno_api_key, "callback_url": st.session_state.callback_url, "task_id": st.session_state.get("task_id", ""), "audio_id": st.session_state.get("audio_id", "") } st.code(json.dumps(config, indent=2), language="json") st.success("๐Ÿ“‹ Configuration copied to clipboard!") # Make API Call Function def make_api_call(task_id, audio_id, api_key, callback_url): with st.spinner("๐ŸŽต Generating audio..."): # Prepare the API call headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } data = { "taskId": task_id, "audioId": audio_id, "callBackUrl": callback_url } # Show request details with st.expander("๐Ÿ“ก Request Details", expanded=False): st.markdown(f""" **Endpoint:** `https://api.sunoapi.org/api/v1/wav/generate` **Headers:** ```python {json.dumps(headers, indent=2)} ``` **Body:** ```json {json.dumps(data, indent=2)} ``` """) # Make the API call try: #response = requests.post("https://api.sunoapi.org/api/v1/wav/generate", headers=headers, json=data) #st.session_state.last_api_response = response.json() # For demo purposes, return a mock response mock_response = { "status": "success", "jobId": "generated_123456789", "estimatedCompletion": "2026-01-17T20:45:00Z", "message": "Audio generation started successfully" } st.session_state.last_api_response = mock_response st.success("โœ… Audio generation started successfully!") # Show job info st.info(f"**Job ID:** {mock_response['jobId']}") st.info(f"**Estimated Completion:** {mock_response['estimatedCompletion']}") except Exception as e: st.error(f"โŒ API call failed: {str(e)}") # Run the main function if __name__ == "__main__": main()