diff --git a/README.md b/README.md index fdbe56e..5beeb65 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,7 @@ Suno API currently mainly implements the following APIs: - `/api/get`: Get music information based on the id. Use “,” to separate multiple ids. If no IDs are provided, all music will be returned. - `/api/get_limit`: Get quota Info +- `/api/extend_audio`: Extend audio length ``` For more detailed documentation, please check out the demo site: @@ -146,6 +147,11 @@ def custom_generate_audio(payload): return response.json() +def extend_audio(payload): + url = f"{base_url}/api/extend_audio" + response = requests.post(url, json=payload, headers={'Content-Type': 'application/json'}) + return response.json() + def generate_audio_by_prompt(payload): url = f"{base_url}/api/generate" response = requests.post(url, json=payload, headers={'Content-Type': 'application/json'}) @@ -209,6 +215,14 @@ async function generateAudioByPrompt(payload) { return response.data; } +async function extendAudio(payload) { + const url = `${baseUrl}/api/extend_audio`; + const response = await axios.post(url, payload, { + headers: { "Content-Type": "application/json" }, + }); + return response.data; +} + async function getAudioInformation(audioIds) { const url = `${baseUrl}/api/get?ids=${audioIds}`; const response = await axios.get(url); @@ -273,13 +287,13 @@ LGPL-3.0 or later ## Contact Us -- Contact us: +- Contact us: ## Related Links - Project repository: [github.com/gcui-art/suno-api](https://github.com/gcui-art/suno-api) - Suno.ai official website: [suno.ai](https://suno.ai) -- Demo: [suno.gcui.art](https://suno.gcui.art) +- Demo: [suno.gcui.ai](https://suno.gcui.ai) ## Statement diff --git a/README_CN.md b/README_CN.md index 1bd5ec9..78491d8 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,7 +33,7 @@ Suno.ai v3 是一个令人惊叹的 AI 音乐服务,虽然官方还没有开 - 完美的实现了 app.suno.ai 中的大部分 API - 自动保持账号活跃 -- 兼容OpenAI的 `/v1/chat/completions` API 格式 +- 兼容 OpenAI 的 `/v1/chat/completions` API 格式 - 支持 Custom Mode - 一键部署到 vercel - 除了标准 API,还适配了 GPTs、coze 等 Agent 平台的 API Schema,所以你可以把它当做一个 LLM 的工具/插件/Action,集成到任意 AI Agent 中。 @@ -120,6 +120,7 @@ Suno API 目前主要实现了以下 API: - `/api/generate_lyrics`: 根据Prompt创建歌词 - `/api/get`: 根据id获取音乐信息。获取多个请用","分隔,不传ids则返回所有音乐 - `/api/get_limit`: 获取配额信息 +- `/api/extend_audio`: 在一首音乐的基础上,扩展音乐长度 ``` 详细文档请查看演示站点: @@ -142,6 +143,11 @@ def custom_generate_audio(payload): response = requests.post(url, json=payload, headers={'Content-Type': 'application/json'}) return response.json() +def extend_audio(payload): + url = f"{base_url}/api/extend_audio" + response = requests.post(url, json=payload, headers={'Content-Type': 'application/json'}) + return response.json() + def generate_audio_by_prompt(payload): url = f"{base_url}/api/generate" @@ -205,6 +211,13 @@ async function generateAudioByPrompt(payload) { }); return response.data; } +async function extendAudio(payload) { + const url = `${baseUrl}/api/extend_audio`; + const response = await axios.post(url, payload, { + headers: { "Content-Type": "application/json" }, + }); + return response.data; +} async function getAudioInformation(audioIds) { const url = `${baseUrl}/api/get?ids=${audioIds}`; @@ -270,13 +283,13 @@ LGPL-3.0 或更高版本 ## 联系方式 -- 联系我们: +- 联系我们: ## 相关链接 - 项目仓库: [github.com/gcui-art/suno-api](https://github.com/gcui-art/suno-api) - Suno.ai 官网: [suno.ai](https://suno.ai) -- 演示站点: [suno.gcui.art](https://suno.gcui.art) +- 演示站点: [suno.gcui.ai](https://suno.gcui.ai) ## 声明 diff --git a/src/app/api/extend_audio/route.ts b/src/app/api/extend_audio/route.ts new file mode 100644 index 0000000..0ba3c58 --- /dev/null +++ b/src/app/api/extend_audio/route.ts @@ -0,0 +1,70 @@ +import { NextResponse, NextRequest } from "next/server"; +import { sunoApi } from "@/lib/SunoApi"; +import { corsHeaders } from "@/lib/utils"; + +export const dynamic = "force-dynamic"; + +export async function POST(req: NextRequest) { + if (req.method === 'POST') { + try { + const body = await req.json(); + const { audio_id, prompt, continue_at, tags, title } = body; + console.log(body) + + if (!audio_id) { + return new NextResponse(JSON.stringify({ error: 'Audio ID is required' }), { + status: 400, + headers: { + 'Content-Type': 'application/json', + ...corsHeaders + } + }); + } + + const audioInfo = await (await sunoApi) + .extendAudio(audio_id, prompt, continue_at, tags, title); + + return new NextResponse(JSON.stringify(audioInfo), { + status: 200, + headers: { + 'Content-Type': 'application/json', + ...corsHeaders + } + }); + } catch (error: any) { + console.error('Error extend audio:', JSON.stringify(error.response.data)); + if (error.response.status === 402) { + return new NextResponse(JSON.stringify({ error: error.response.data.detail }), { + status: 402, + headers: { + 'Content-Type': 'application/json', + ...corsHeaders + } + }); + } + return new NextResponse(JSON.stringify({ error: 'Internal server error: ' + JSON.stringify(error.response.data.detail) }), { + status: 500, + headers: { + 'Content-Type': 'application/json', + ...corsHeaders + } + }); + } + } else { + return new NextResponse('Method Not Allowed', { + headers: { + Allow: 'POST', + ...corsHeaders + }, + status: 405 + }); + } +} + + +export async function OPTIONS(request: Request) { + return new Response(null, { + status: 200, + headers: corsHeaders + }); +} \ No newline at end of file diff --git a/src/app/docs/page.tsx b/src/app/docs/page.tsx index ea931c2..2a53426 100644 --- a/src/app/docs/page.tsx +++ b/src/app/docs/page.tsx @@ -28,6 +28,7 @@ export default function Docs() { - \`/api/get\`: Get music information based on the id. Use “,” to separate multiple ids. If no IDs are provided, all music will be returned. - \`/api/get_limit\`: Get quota Info +- \`/api/extend_audio\`: Extend audio length \`\`\` Feel free to explore the detailed API parameters and conduct tests on this page. diff --git a/src/app/docs/swagger-suno-api.json b/src/app/docs/swagger-suno-api.json index f2fe496..4d4936e 100644 --- a/src/app/docs/swagger-suno-api.json +++ b/src/app/docs/swagger-suno-api.json @@ -179,6 +179,50 @@ } } }, + "/api/extend_audio": { + "post": { + "summary": "Extend audio length.", + "description": "Extend audio length.", + "tags": ["default"], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["audio_id"], + "properties": { + "audio_id": { + "type": "string", + "description": "The ID of the audio clip to extend.", + "example": "e76498dc-6ab4-4a10-a19f-8a095790e28d" + }, + "prompt": { + "type": "string", + "description": "Detailed prompt, including information such as music lyrics.", + "example": "" + }, + "continue_at": { + "type": "string", + "description": "Extend a new clip from a song at mm:ss(e.g. 00:30). Default extends from the end of the song.", + "example": "109.96" + }, + "title": { + "type": "string", + "description": "Music title", + "example": "" + }, + "tags": { + "type": "string", + "description": "Music genre", + "example": "" + } + } + } + } + } + } + } + }, "/api/generate_lyrics": { "post": { "summary": "Generate lyrics based on Prompt.", diff --git a/src/app/page.tsx b/src/app/page.tsx index 3be0ccc..2d87bda 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -105,6 +105,7 @@ Suno API currently mainly implements the following APIs: - \`/api/get\`: Get music list - \`/api/get?ids=\`: Get music Info by id, separate multiple id with ",". - \`/api/get_limit\`: Get quota Info +- \`/api/extend_audio\`: Extend audio length \`\`\` For more detailed documentation, please check out the demo site: diff --git a/src/lib/SunoApi.ts b/src/lib/SunoApi.ts index 414e7a2..f332b0a 100644 --- a/src/lib/SunoApi.ts +++ b/src/lib/SunoApi.ts @@ -255,6 +255,34 @@ class SunoApi { return lyricsResponse.data; } + /** + * Extends an existing audio clip by generating additional content based on the provided prompt. + * + * @param audioId The ID of the audio clip to extend. + * @param prompt The prompt for generating additional content. + * @param continueAt Extend a new clip from a song at mm:ss(e.g. 00:30). Default extends from the end of the song. + * @param tags Style of Music. + * @param title Title of the song. + * @returns A promise that resolves to an AudioInfo object representing the extended audio clip. + */ + public async extendAudio( + audioId: string, + prompt: string = "", + continueAt: string = "0", + tags: string = "", + title: string = "" + ): Promise { + const response = await this.client.post(`${SunoApi.BASE_URL}/api/generate/v2/`, { + continue_clip_id: audioId, + continue_at: continueAt, + mv: "chirp-v3-0", + prompt: prompt, + tags: tags, + title: "" + }); + return response.data; + } + /** * Processes the lyrics (prompt) from the audio metadata into a more readable format. * @param prompt The original lyrics text. @@ -327,7 +355,7 @@ const newSunoApi = async (cookie: string) => { return await sunoApi.init(); } -if (! process.env.SUNO_COOKIE) { +if (!process.env.SUNO_COOKIE) { console.log("Environment does not contain SUNO_COOKIE.", process.env) }