GithubHelp home page GithubHelp logo

sunoai-api / suno-api Goto Github PK

View Code? Open in Web Editor NEW
1.3K 4.0 168.0 1.84 MB

This is an unofficial Suno AI API based on Python and FastAPI. It currently supports generating songs, lyrics, etc.需要 suno API的可以看看这里👇

Home Page: https://www.sunoaiapi.com

License: MIT License

Python 97.43% Dockerfile 2.57%
suno-ai suno-ai-api suno

suno-api's Introduction

简体中文 | 日本語

Good news

I provide the Suno AI API, no deployment is required, no subscription to suno is required. Lower price, more convenient to use the suno API. Website: http://app.sunoaiapi.com

Unofficial API

This is an unofficial API based on Python and FastAPI. It currently supports generating songs, lyrics, etc.
It comes with a built-in token maintenance and keep-alive feature, so you don't have to worry about the token expiring.

Features

  • Automatic token maintenance and keep-alive
  • Fully asynchronous, fast, suitable for later expansion
  • Simple code, easy to maintain, convenient for secondary development

Contact me

https://t.me/austin2035

group

Usage

Configuration

Edit the .env.example file, rename to .env and fill in the session_id and cookie.

These are initially obtained from the browser, and will be automatically kept alive later.

cookie

Run

Install dependencies

pip3 install -r requirements.txt

For this part, refer to the FastAPI documentation on your own.

uvicorn main:app 

Docker

docker compose build && docker compose up

Documentation

After setting up the service, visit /docs

docs

Useful resources

chatgpt web, midjourney, gpts,tts, whisper,suno-v3

suno-api's People

Contributors

austin2035 avatar cnwutong avatar eltociear avatar jousejg avatar thatsinewave avatar trouvaille0198 avatar waitkafuka avatar wengchaoxi avatar zzhbible avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

suno-api's Issues

Service unavailable

Recently suno disabled the service with, quote

Making songs is currently disabled while we upgrade our infrastructure. You can still listen to your favorite tunes.

This can be detected via {'detail': "Service unavailable"} response from /generate.
Is it possible to detect this without actually calling /generate ?

[Generate/concat] Missleading function : i'm unable to process a concatenation

Sadly, i can't concatenate at the moment.

Concatenating songs with V1 ID: 186fa21c-f5c7-4af5-8fd4-5112f4486e31 and V2 ID: 5ed9894f-2208-47ed-8210-a35c8545927b
Failed to concatenate songs: 500 Server Error: Internal Server Error for url: https://api.sunoaiapi.com/api/v1/gateway/generate/concat

Here is a snippet:

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

Thanks in advance

install error

Collecting dotenv (from -r requirements.txt (line 2))
Using cached dotenv-0.0.5.tar.gz (2.4 kB)
Installing build dependencies ... done
Getting requirements to build wheel ... done
Installing backend dependencies ... error
error: subprocess-exited-with-error

× pip subprocess to install backend dependencies did not run successfully.
│ exit code: 1
╰─> [34 lines of output]
Collecting distribute
Using cached distribute-0.7.3.zip (145 kB)
Installing build dependencies: started
Installing build dependencies: finished with status 'done'
Getting requirements to build wheel: started
Getting requirements to build wheel: finished with status 'done'
Preparing metadata (pyproject.toml): started
Preparing metadata (pyproject.toml): finished with status 'error'
error: subprocess-exited-with-error

    Preparing metadata (pyproject.toml) did not run successfully.
    exit code: 1

    [6 lines of output]
    usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
       or: setup.py --help [cmd1 cmd2 ...]
       or: setup.py --help-commands
       or: setup.py cmd --help

    error: invalid command 'dist_info'
    [end of output]

    note: This error originates from a subprocess, and is likely not a problem with pip.
  error: metadata-generation-failed

  Encountered error while generating package metadata.

  See above for output.

  note: This is an issue with the package mentioned above, not pip.
  hint: See above for details.

  [notice] A new release of pip is available: 23.1.2 -> 24.0
  [notice] To update, run: python.exe -m pip install --upgrade pip
  [end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

HelloGitHub Badge

🎉 Congratulations! Your project has been featured and recommended by the HelloGitHub community. We invite you to join the HelloGitHub Badge Program. Joining will grant you the following privileges:

  • Community Recognition: The badge indicates that your project has successfully passed the HelloGitHub community's stringent selection and recommendation process.
  • Increased Exposure: Displaying the badge will draw more traffic to your project, attracting additional users and contributors.
  • Enhanced Interaction: Users can quickly understand your project through the badge and engage with it (like, comment, bookmark).
  • Feedback Collection: Gather genuine feedback from a broad user base, aiding in the continuous improvement of your project.
  • Special Identification: Once verified, your comments will feature a distinctive mark and be prioritized for pinning.

📌 Click here to wear the badge and join the HelloGitHub Badge Program, allowing your open-source project to shine even brighter.


HelloGitHub is a community focused on discovering, sharing, and promoting open-source projects. Since its inception in 2016, it has grown from a monthly newsletter into a dynamic community with over 10,000 users. Our footprint extends across multiple content platforms, earning the trust and support of 500,000 fans worldwide.

截屏2024-06-12 09 29 42

[PROMPT in API3] - Question

Hi,
"Prompt" in API3 seems to be both for generating songs based on prompting and lyrics generation, but also for lyrics directly sent to the API. I'm on the right track?

Aniway, in my case, with 3.5 version from Suno.ai, we can handle up to 4 min generation but "Prompt" key can't handle that much characters.
Is that supposed to evolve or i'm misleading myself with the "prompt" key and there is another way to sent "large lyrics" ?

Thanks in advance

Tests produce 422 Unprocessable Entity

Running some tests from tests.py:

INFO:     Started server process [1813280]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     127.0.0.1:55394 - "POST /generate/description-mode HTTP/1.1" 422 Unprocessable Entity
INFO:     127.0.0.1:38478 - "POST /generate/description-mode HTTP/1.1" 422 Unprocessable Entity
INFO:     127.0.0.1:46720 - "POST /generate HTTP/1.1" 422 Unprocessable Entity

Did Suno change the way the session and cookie is logged?

All of the sudden my code stopped working today and I am getting "unauthorized" as an error message. I re-added the session ID and cookie, but it is still not working.

Can you try your code and try to hit the Suno AI API and let me know if something changed?

Automatic token refresh

I am running the Suno API properly, however i notice every 7 days, i have to update my session id and cookie value.

In the readme it says: "Automatic token maintenance and keep-alive"
How can i make sure my token gets properly refreshed, without me having to manually update this information?

The cookies are not auto-updating

Hello,
and thanks for your hard work on this!

The readme says:

Automatic token maintenance and keep-alive

But I find this not to be the case for me, as every exactly 7 days the API starts returning Unauthorized and I have to go add new cookies manually.

Is anyone else experiencing this? Anything I can do?

Thanks!

Retrieve Audio URL?

Hello:

My code works and the song is generated in Suno AI's website. However, the program is unable to download the song because the Audio URL is not being generated. Only the song ID is outputted, which is different from the URL to download the song.
import os
import requests
from dotenv import load_dotenv
import time

Load environment variables from .env file

load_dotenv()

def get_song_status(song_id):
api_url = f"http://127.0.0.1:8000/api/feed/?ids={song_id}"
response = requests.get(api_url)
print("Attempting to retrieve song status with ID:", song_id)
print("API URL being called:", api_url)
if response.status_code == 200:
print("Full response data:", response.json())
return response.json()
else:
print("Failed to retrieve song status. Status Code:", response.status_code)
print("Response:", response.text)
return None

def wait_for_song(song_id, timeout=300):
start_time = time.time()
while time.time() - start_time < timeout:
song_data = get_song_status(song_id)
if song_data and 'audio_url' in song_data:
print("Audio URL found:", song_data['audio_url'])
return song_data['audio_url']
time.sleep(10) # Wait before checking again
print("Timed out waiting for the song to be available.")
return None

def initiate_song_generation(description):
url = "http://127.0.0.1:8000/generate/description-mode"
data = {
"gpt_description_prompt": description,
"make_instrumental": False,
"mv": "chirp-v3-0"
}
response = requests.post(url, json=data)
if response.status_code == 200:
response_data = response.json()
print("Response Data from Generation:", response_data)
song_id = response_data.get('id')
print(f"Song generation initiated successfully. Song ID: {song_id}")
return song_id
else:
print("Failed to initiate song generation:", response.text)
return None

def download_song(audio_url):
response = requests.get(audio_url)
if response.status_code == 200:
filename = audio_url.split('/')[-1]
with open(filename, 'wb') as f:
f.write(response.content)
print(f"Song downloaded successfully: {filename}")
else:
print("Failed to download the song:", response.text)

def main():
description = input("Enter a description for the song you want to generate: ")
song_id = initiate_song_generation(description)
if song_id:
print("Waiting for song to be processed...")
audio_url = wait_for_song(song_id)
if audio_url:
print(f"Song ready! Downloading from: {audio_url}")
download_song(audio_url)
else:
print("Song processing failed or took too long.")

if name == "main":
main()

how to use instrumental button

WeChat4f174b9b1ffd99c7f5c722fd8e7f7faa

curl -X 'POST'
'http://127.0.0.1:8000/generate'
-H 'accept: application/json'
-H 'Content-Type: application/json'
-d '{
"prompt": "",
"mv": "chirp-v3-0",
"title": "hello world",
"tags": "Pop, folk, easy listening, anime, blues, country, classical"
}'

It will still produce songs with lyrics, are there any parameters that need to be added?

Can't resolve my unauthorized issue

I've been working with the API code to have it run locally within an app of mine, but I'm running into the {detail: Unauthorized} bug that I can't get around when I call generate(). Here's my full code -- no issues before the generate call.

Is there a reason this code can't work locally or on its own in a single py file? would appreciate if you could pass in your session and cookie info and see if this works for you.


from datetime import datetime
from typing import Any, List, Optional, Union

from pydantic import BaseModel, Field
import asyncio

class schemas:
    class Response(BaseModel):
        code: Optional[int] = 0
        msg: Optional[str] = "success"
        data: Optional[Any] = None

    class CustomModeGenerateParam(BaseModel):
        """Generate with Custom Mode"""
        prompt: str = Field(..., description="lyrics")
        mv: str = Field(..., description="model version, default: chirp-v3-0", examples=["chirp-v3-0"])
        title: str = Field(..., description="song title")
        tags: str = Field(..., description="style of music")
        continue_at: Optional[int] = Field(default=None, description="continue a new clip from a previous song, format number", examples=[120])
        continue_clip_id: Optional[str] = None

    class DescriptionModeGenerateParam(BaseModel):
        """Generate with Song Description"""
        gpt_description_prompt: str
        make_instrumental: bool = False
        mv: str = Field(default='chirp-v3-0', description="model version, default: chirp-v3-0", examples=["chirp-v3-0"])
        prompt: str = Field(default="", description="Placeholder, keep it as an empty string, do not modify it")

## UTILS

import json
import os
import time

import aiohttp
# from dotenv import load_dotenv

# load_dotenv()

# BASE_URL = os.getenv("BASE_URL")

BASE_URL = "https://studio-api.suno.ai"

COMMON_HEADERS = {
    "Content-Type": "text/plain;charset=UTF-8",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
    "Referer": "https://suno.com",
    "Origin": "https://suno.com",
}


async def fetch(url, headers=None, data=None, method="POST"):
    if headers is None:
        headers = {}
    headers.update(COMMON_HEADERS)
    if data is not None:
        data = json.dumps(data)

    print(data, method, headers, url)

    async with aiohttp.ClientSession() as session:
        try:
            async with session.request(
                method=method, url=url, data=data, headers=headers
            ) as resp:
                return await resp.json()
        except Exception as e:
            return f"An error occurred: {e}"


async def get_feed(ids, token):
    headers = {"Authorization": f"Bearer {token}"}
    api_url = f"{BASE_URL}/api/feed/?ids={ids}"
    response = await fetch(api_url, headers, method="GET")
    return response


async def generate_music(data, token):
    headers = {"Authorization": f"Bearer {token}"}
    api_url = f"{BASE_URL}/api/generate/v2/"
    print(api_url, headers)
    response = await fetch(api_url, headers, data)
    return response


async def generate_lyrics(prompt, token):
    headers = {"Authorization": f"Bearer {token}"}
    api_url = f"{BASE_URL}/api/generate/lyrics/"
    data = {"prompt": prompt}
    return await fetch(api_url, headers, data)


async def get_lyrics(lid, token):
    headers = {"Authorization": f"Bearer {token}"}
    api_url = f"{BASE_URL}/api/generate/lyrics/{lid}"
    return await fetch(api_url, headers, method="GET")


## cookie

import os
import time
from http.cookies import SimpleCookie
from threading import Thread

import requests

# from utils import COMMON_HEADERS


class SunoCookie:
    def __init__(self):
        self.cookie = SimpleCookie()
        self.session_id = None
        self.token = None

    def load_cookie(self, cookie_str):
        self.cookie.load(cookie_str)

    def get_cookie(self):
        return ";".join([f"{i}={self.cookie.get(i).value}" for i in self.cookie.keys()])

    def set_session_id(self, session_id):
        self.session_id = session_id

    def get_session_id(self):
        return self.session_id

    def get_token(self):
        return self.token

    def set_token(self, token: str):
        self.token = token





def update_token(suno_cookie: SunoCookie):
    headers = {"cookie": suno_cookie.get_cookie()}
    headers.update(COMMON_HEADERS)
    session_id = suno_cookie.get_session_id()

    resp = requests.post(
        url=f"https://clerk.suno.com/v1/client/sessions/{session_id}/tokens?_clerk_js_version=4.72.0-snapshot.vc141245",
        headers=headers,
    )

    resp_headers = dict(resp.headers)
    set_cookie = resp_headers.get("Set-Cookie")
    suno_cookie.load_cookie(set_cookie)
    token = resp.json().get("jwt")
    suno_cookie.set_token(token)
    # print(set_cookie)
    # print(f"*** token -> {token} ***")


def keep_alive(suno_cookie: SunoCookie):
    while True:
        try:
            update_token(suno_cookie)
        except Exception as e:
            print(e)
        finally:
            time.sleep(5)


def start_keep_alive(suno_cookie: SunoCookie):
    t = Thread(target=keep_alive, args=(suno_cookie,))
    t.start()


import json
from fastapi import Depends, HTTPException, status

async def get_root():
    return schemas.Response()

async def generate(data: schemas.CustomModeGenerateParam, token: str = Depends(get_token)):
    try:
        resp = await generate_music(data.dict(), token)
        return resp
    except Exception as e:
        raise HTTPException(
            detail=str(e),
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

async def generate_with_song_description(data: schemas.DescriptionModeGenerateParam, token: str = Depends(get_token)):
    try:
        resp = await generate_music(data.dict(), token)
        return resp
    except Exception as e:
        raise HTTPException(
            detail=str(e),
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

async def fetch_feed(aid: str, token: str = Depends(get_token)):
    try:
        resp = await get_feed(aid, token)
        return resp
    except Exception as e:
        raise HTTPException(
            detail=str(e),
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

async def generate_lyrics_post(prompt: str, token: str = Depends(get_token)):
    if prompt is None:
        raise HTTPException(
            detail="prompt is required",
            status_code=status.HTTP_400_BAD_REQUEST
        )
    try:
        resp = await generate_lyrics(prompt, token)
        return resp
    except Exception as e:
        raise HTTPException(
            detail=str(e),
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

async def fetch_lyrics(lid: str, token: str = Depends(get_token)):
    try:
        resp = await get_lyrics(lid, token)
        return resp
    except Exception as e:
        raise HTTPException(
            detail=str(e),
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

cookie_new = "replace this"
session = "replace this"

suno_auth = SunoCookie()
suno_auth.set_session_id(session)
suno_auth.load_cookie(cookie_new)

start_keep_alive(suno_auth)

def get_token():
  token = suno_auth.get_token()
  try:
      yield token
  finally:
      pass
  
tags = "fast, chill, happy"
prompt = """\[Verse 1\] Walking down the street The city's shining bright Neon signs are glowing Colors catching my sight (ooh-yeah) People passing by In a hurry Out of time Caught up in the chaos of this city's daily grind \[Verse 2\] Taxis honking horns Sirens fill the air Skyscrapers reaching high A bustling affair (ooh-ooh) Nightclubs pumping beats Dance floors packed tight Everyone's searching for a taste of the nightlife \[Chorus\] Lost in the city lights I feel the energy ignite Moving to the rhythm Partying into the night Living for the moment Taking in the sights Lost in the city lights We're catching dreams in flight"""

data_test = schemas.CustomModeGenerateParam(
    title="City Lights",
    tags=tags,
    prompt=prompt,
    mv="chirp-v3-0"
)

# Run the coroutine and get the result
async def main():
    result = await generate(data=data_test)
    print(result)

# Create an event loop and run the main function
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()```

无法链接suno.ai

HTTPSConnectionPool(host='clerk.suno.ai', port=443): Max retries exceeded with url: /v1/client/sessions/sess_2eIknoT0bT7smQLtUQiTZ9dTePi/tokens?_clerk_js_version=4.70.5 (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f15c1444828>: Failed to establish a new connection: [Errno -2] Name or service not known',))

mistake in docs

There is a mistake in docs
"/generate/lyrics/" needs a body contains "prompt"
like {"prompt": "A soothing lullaby"}
Snipaste_2024-04-24_19-43-30

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.