gcui-art / suno-api

Use API to call the music generation AI of suno.ai, and easily integrate it into agents like GPTs.
https://suno.gcui.ai
GNU Lesser General Public License v3.0
872 stars 194 forks source link

[Ask for Review] - send_lyrics_to_api #89

Closed sKunZel closed 3 weeks ago

sKunZel commented 1 month ago

If you could review it and find a solution. Would be great.

Thanks in advance.

def send_lyrics_to_api(song):
    url = 'https://api.sunoaiapi.com/api/v1/gateway/generate/music'
    headers = {'Content-Type': 'application/json', 'api-key': API_KEY}
    payload = {
        "prompt": song[2],
        "tags": song[1],
        "title": song[0],
        "wait_audio": False  # Set to false for background processing
    }
    try:
        print(f"Sending request to {url} with payload: {payload}")
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()
        data = response.json()
        print(f"Response from API: {data}")
        if 'data' in data and len(data['data']) == 2:
            song_ids = [data['data'][0]['song_id'], data['data'][1]['song_id']]
            print(f"Successfully submitted: {song[0]}, IDs: {song_ids}")
            return song_ids
        else:
            print(f"Unexpected response structure: {data}")
            return None
    except requests.exceptions.RequestException as e:
        print(f"Failed to submit {song[0]}: {e}")
        return None
                           ------------------------------------------------------------
def **query_generation_status**(song_ids):
    **url = f"https://api.sunoaiapi.com/api/v1/gateway/query?ids={','.join(song_ids)}"**
    **headers = {'Content-Type': 'application/json', 'api-key': API_KEY}**
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        data = response.json()
        if isinstance(data, list):
            return data
        else:
            print(f"Unexpected response structure: {data}")
            return []
    else:
        print(f"Failed to query generation status with status: {response.status_code}, Response: {response.text}")
    return []
sKunZel commented 1 month ago

Because i have an error 401 : Unauthorized for url: https://api.sunoaiapi.com/api/v1/gateway/generate/music

On this actual code :

import os
import requests
import time
from dotenv import load_dotenv
from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build

# Charger les variables d'environnement
load_dotenv()

# Assurez-vous que les variables d'environnement sont correctement définies
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly', 'https://www.googleapis.com/auth/spreadsheets']
SERVICE_ACCOUNT_FILE = os.getenv('GOOGLE_APPLICATION_CREDENTIALS')
API_KEY = os.getenv('API_KEY')
SPREADSHEET_ID = '1quC9U5fgmDQDPw-bqzqkyGfK5uZIkQbV5YSGKGM7xfo'  # ID de la feuille de calcul
RANGE_NAME = 'Feuille 1!A3:C'

def get_google_sheets_service():
    creds = Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    service = build('sheets', 'v4', credentials=creds)
    return service

def get_lyrics_from_sheet(spreadsheet_id, range_name):
    service = get_google_sheets_service()
    sheet = service.spreadsheets()
    result = sheet.values().get(spreadsheetId=spreadsheet_id, range=range_name).execute()
    values = result.get('values', [])
    if not values:
        print("No data found.")
    return values

def send_lyrics_to_api(song):
    url = 'https://api.sunoaiapi.com/api/v1/gateway/generate/music'
    headers = {'Content-Type': 'application/json', 'api-key': API_KEY}
    payload = {
        "prompt": song[2],
        "tags": song[1],
        "title": song[0],
        "wait_audio": False  # Set to false for background processing
    }
    try:
        print(f"Sending request to {url} with payload: {payload}")
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()
        data = response.json()
        print(f"Response from API: {data}")
        if 'data' in data and len(data['data']) == 2:
            song_ids = [data['data'][0]['song_id'], data['data'][1]['song_id']]
            print(f"Successfully submitted: {song[0]}, IDs: {song_ids}")
            return song_ids
        else:
            print(f"Unexpected response structure: {data}")
            return None
    except requests.exceptions.RequestException as e:
        print(f"Failed to submit {song[0]}: {e}")
        return None

def query_generation_status(song_ids):
    url = f"https://api.sunoaiapi.com/api/v1/gateway/query?ids={','.join(song_ids)}"
    headers = {'Content-Type': 'application/json', 'api-key': API_KEY}
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        data = response.json()
        return data
    except requests.exceptions.RequestException as e:
        print(f"Failed to query generation status: {e}")
        return None

def concatenate_songs(v1_id, v2_id):
    url = 'https://api.sunoaiapi.com/api/v1/gateway/generate/concat'
    headers = {'Content-Type': 'application/json', 'api-key': API_KEY}
    payload = {"clip_id": v2_id}
    try:
        print(f"Concatenating songs with V1 ID: {v1_id} and V2 ID: {v2_id}")
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()
        data = response.json()
        print(f"Response from concatenation API: {data}")
        if 'data' in data and 'song_id' in data['data']:
            concat_id = data['data']['song_id']
            print(f"Successfully concatenated V1 and V2: {v1_id} + {v2_id} = {concat_id}")
            return concat_id
        else:
            print(f"Unexpected response structure: {data}")
            return None
    except requests.exceptions.RequestException as e:
        print(f"Failed to concatenate songs: {e}")
        return None

def download_audio(url, filename):
    try:
        print(f"Downloading audio from {url}")
        response = requests.get(url)
        response.raise_for_status()
        with open(filename, 'wb') as f:
            f.write(response.content)
        print(f"Successfully downloaded audio to {filename}")
    except requests.exceptions.RequestException as e:
        print(f"Failed to download audio from {url}: {e}")

def update_sheet_with_text(spreadsheet_id, values, start_row):
    service = get_google_sheets_service()
    range_name = f'Feuille 1!D{start_row}'
    body = {'values': values}
    try:
        result = service.spreadsheets().values().update(
            spreadsheetId=spreadsheet_id, range=range_name,
            valueInputOption='RAW', body=body).execute()
        print(f"{result.get('updatedCells')} cells updated.")
    except Exception as e:
        print(f"Failed to update sheet: {e}")

if __name__ == "__main__":
    songs = get_lyrics_from_sheet(SPREADSHEET_ID, RANGE_NAME)
    if songs:
        for idx in range(0, len(songs), 2):
            if idx + 1 >= len(songs):
                continue

            song_v1 = songs[idx]
            song_v2 = songs[idx + 1]

            if not song_v1 or not song_v2 or len(song_v1) < 3 or len(song_v2) < 3:
                continue

            title_v1 = song_v1[0]
            title_v2 = song_v2[0]

            if title_v1 != title_v2:
                print(f"Titles do not match for V1 and V2: {title_v1} != {title_v2}")
                continue

            song_ids_v1 = send_lyrics_to_api(song_v1)
            if not song_ids_v1:
                print(f"Failed to send V1 for song: {title_v1}")
                continue

            song_ids_v2 = send_lyrics_to_api(song_v2)
            if not song_ids_v2:
                print(f"Failed to send V2 for song: {title_v2}")
                continue

            v1_complete = False
            v2_complete = False

            while not (v1_complete and v2_complete):
                data_v1 = query_generation_status(song_ids_v1)
                data_v2 = query_generation_status(song_ids_v2)

                if data_v1 and all(song['status'] == 'complete' for song in data_v1['data']):
                    v1_complete = True
                    print(f"V1 generation complete for song: {title_v1}")

                if data_v2 and all(song['status'] == 'complete' for song in data_v2['data']):
                    v2_complete = True
                    print(f"V2 generation complete for song: {title_v2}")

                if not v1_complete or not v2_complete:
                    print(f"V1 or V2 not complete for song: {title_v1}. Retrying in 30 seconds...")
                    time.sleep(30)

            concat_id = concatenate_songs(song_ids_v1[0], song_ids_v2[0])
            if not concat_id:
                print(f"Failed to concatenate songs for: {title_v1}")
                continue

            while True:
                concat_result = query_generation_status([concat_id])
                if concat_result:
                    status = concat_result['data'][0]['status']
                    if status == 'complete':
                        audio_url = concat_result['data'][0]['audio_url']
                        output_filename = f"{title_v1}_complete.mp3"
                        download_audio(audio_url, output_filename)
                        print(f"Successfully downloaded concatenated song: {output_filename}")

                        song_text = concat_result['data'][0]['meta_prompt']
                        start_row = 4 + idx * 2
                        update_sheet_with_text(SPREADSHEET_ID, [[song_text]], start_row)
                        break
                    elif status == 'error':
                        error_message = concat_result['data'][0].get('meta_error_msg', 'Unknown error')
                        print(f"Failed to concatenate song {title_v1}: {error_message}")
                        start_row = 4 + idx * 2
                        update_sheet_with_text(SPREADSHEET_ID, [["Error in concatenation: " + error_message]], start_row)
                        break
                    else:
                        print(f"Concatenated song {title_v1} is in status: {status}. Retrying in 30 seconds...")
                        time.sleep(30)
                else:
                    print(f"Failed to query status for concatenated song {title_v1}. Retrying in 30 seconds...")
                    time.sleep(30)
    else:
        print("No songs found or an error occurred while fetching songs.")
blueeon commented 3 weeks ago

It looks like you may have made a mistake. Your code seems to be referencing a different Suno API project. 🫠