API de încărcare și cover într-un singur pas
Descrierea endpoint-ului
Încărcarea și cover-ul într-un singur pas trimite un fișier audio sau un URL audio și generează o nouă versiune de cover din acel audio sursă.
Endpoint: POST /api/music/upload-cover
Facturare: Cu plată, momentan implicit 0,6 ¥ per apel. Acest endpoint este „încarcă și fă cover”, nu este vorba despre încărcarea unei coperte imagine. Suma efectiv debitată urmează configurația actuală de prețuri din back-office.
Max Mode / Variety: acest endpoint acceptă parametrii opționali max_mode și variety (0-4). Cu
max_mode activat, acest apel este facturat la dublu (0,6 → 1,2 ¥ per apel); variety nu costă
nimic în plus. Ce înseamnă și cum se trimit este în secțiunea „Parametri avansați” din
Prezentarea noului API.
Timpii de așteptare și timeout-urile (important): este un endpoint sincron — comanda este acceptată și transmisă spre generare doar când sosește răspunsul. Din măsurători, majoritatea cererilor răspund în 1-3 secunde, circa 10% depășesc 30 de secunde, iar cea mai lungă este de aproximativ 230 de secunde. Setează timeout-ul clientului la 300 de secunde sau mai mult; lipsa unui răspuns nu înseamnă că nu s-a generat nimic, iar reîncercarea imediat după un timeout dublează comanda și debitează din nou. Dacă conexiunea s-a întrerupt, verifică mai târziu cu
GET /api/music/songs. Vezi „Timpii de așteptare și setarea timeout-ului” în Prezentarea noului API.
Când audio-ul este mare, este mai bine să împarți „încărcarea” și „cover-ul” în doi pași (recomandat)
Acest endpoint cere ca tot audio-ul să intre în corpul cererii: cu cât audio-ul e mai mare, cu atât corpul e mai mare, iar o singură fluctuație de rețea sau un timeout întrerupe transferul la jumătate, după care serverul returnează
unexpected end of JSON input(HTTP 400, fără debitare).Când audio-ul depășește aproximativ 8 MB, rețeaua este instabilă sau același material sursă va fi reutilizat, treci la forma în doi pași:
POST /api/music/upload-sourceîncarcă mai întâi audio-ul sursă — gratuit, se poate reîncerca oricând — și returnează unclip_id;POST /api/music/generate-from-sourcepornește cover-ul cu acelclip_id— corpul pasului cu plată are doar aproximativ 250 de octeți.Vezi API-ul de încărcare a audio-ului sursă, API-ul de cover dintr-un clip sursă și „Fișiere mari și cereri trunchiate” la finalul acestei pagini.
Parametrii cererii
Headers
| Parametru | Tip | Obligatoriu | Observații |
|---|---|---|---|
| Authorization | string | da | Bearer YOUR_API_KEY |
| Content-Type | string | da | application/json |
Parametri din body
| Parametru | Tip | Obligatoriu | Implicit | Observații |
|---|---|---|---|---|
| model | string | nu | suno-v6 | Nume de model pentru client: suno-v6, suno-v6-wild sau suno-v6-mini |
| file_url | string | nu | - | URL-ul audio-ului sursă |
| file_base64 | string | nu | - | Audio în Base64 |
| file_name | string | nu | - | Numele fișierului |
| prompt | string | nu | - | Versuri noi sau direcția adaptării |
| style | string | nu | - | Etichete de stil |
| title | string | nu | - | Titlu |
| negativeTags | string | nu | - | Stil negativ |
| instrumental | boolean | nu | false | Dacă piesa este instrumentală |
| waitAudio | boolean | nu | false | Dacă se așteaptă finalizarea audio-ului |
| cover_start_s | number | nu | - | Secunda de început a fragmentului refăcut |
| cover_end_s | number | nu | - | Secunda de final a fragmentului refăcut |
| audio_weight | number | nu | - | Dependența de audio-ul de referință, interval 0.0-1.0; poate fi trimis doar când se furnizează audio de referință |
cover_start_s și cover_end_s sunt în secunde și pot fi zecimale; timpul de început trebuie să fie mai mic decât cel de final și nu poate depăși durata audio-ului sursă. Dacă ambele câmpuri sunt omise, se folosește tot audio-ul. audio_weight corespunde câmpului metadata.control_sliders.audio_weight din Suno și controlează cât de mult se sprijină rezultatul pe audio-ul de referință; ia valori 0.0-1.0 și poate fi inclus doar când cererea furnizează audio de referință valid prin file_url sau file_base64. 0 este o valoare validă; omiterea câmpului înseamnă „nespecificat” și păstrează comportamentul implicit al Suno. instrumental și waitAudio trebuie să fie valori booleene JSON, nu șiruri.
Endpoint-ul de încărcare răspunde implicit asincron. Cât timp clips[].status din răspuns este pending, un audio_url gol este normal și nu înseamnă că încărcarea sau cover-ul au eșuat; salvează song_id-ul real returnat și interoghează endpoint-ul de căutare a pieselor până la finalizare înainte de a citi adresa audio.
Exemplu de cerere
curl -X POST https://www.suno-api.io/api/music/upload-cover \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"file_url": "https://example.com/source.mp3",
"file_name": "source.mp3",
"prompt": "Versuri noi sau direcția adaptării",
"style": "Mandopop, acoustic guitar",
"title": "Versiune cover",
"negativeTags": "noise, low quality",
"audio_weight": 0.5,
"instrumental": false,
"waitAudio": false,
"cover_start_s": 0,
"cover_end_s": 60
}'
Răspuns
{
"code": 200,
"message": "success",
"data": {
"upload": {
"clip_id": "uploaded_clip_id",
"status": "complete"
},
"clips": [
{
"song_id": "new_clip_id",
"song_title": "Versiune cover",
"status": "pending"
}
]
}
}
Fișiere mari și cereri trunchiate
Recomandat: împărțirea încărcării și a cover-ului în doi pași
Endpoint-ul de o singură dată (acesta) unește încărcarea și generarea într-un singur pas: corpul mare stă în acel unic pas, așa că la o întrerupere nu știi nici dacă s-a generat ceva, nici dacă s-a debitat.
| Pasul 1 încărcare | Pasul 2 cover | |
|---|---|---|
| Endpoint | POST /api/music/upload-source |
POST /api/music/generate-from-source |
| Facturare | Gratuit (doar încărcare, fără generare) | 0,6 ¥ per apel; 1,2 ¥ per apel cu Max Mode |
| Corpul cererii | Audio-ul în sine (base64 / multipart) sau doar un link prin file_url |
Aproximativ 250 de octeți (doar un sourceClipId) |
| Returnează | clip_id (clip ID-ul audio-ului sursă) |
data.clips[].song_id (rezultatul generat) |
| Dacă eșuează | Reîncearcă pur și simplu, fără debitare și fără sarcină de generare | Setează timeout-ul clientului la ≥300 s; la timeout verifică mai întâi cu /api/music/songs și nu reîncerca imediat |
| Reutilizarea materialului sursă | Același clip_id merge și pentru extindere / înlocuire / separare |
Audio-ul trebuie reîncărcat de fiecare dată |
Concluzie: audio peste aproximativ 8 MB, rețea instabilă sau același material folosit de mai multe ori → folosește forma în doi pași; audio mic pe o rețea stabilă → acest endpoint e mai comod.
Ce înseamnă 400 unexpected end of JSON input
Înseamnă că JSON-ul primit de server este incomplet (nu e un parametru greșit, nici o problemă de permisiuni sau de sold). Cauzele obișnuite, în ordinea probabilității:
- Un corp mare trunchiat la mijlocul transferului: stratul de intrare înregistrează atât „câți octeți a declarat clientul”, cât și „câți au ajuns efectiv”. Caz măsurat: clientul a declarat 14,17 MB și au ajuns doar 11,8–12,4 MB, iar toate cele trei cereri s-au oprit în jurul a 1,6–1,7 s; numărul de octeți lipsă a diferit de fiecare dată, ceea ce indică o întrerupere a transferului și nu o limită fixă (serverul nu limitează dimensiunea corpului).
Content-Lengthcare nu corespunde octeților trimiși efectiv: în Node.js, folosirea.lengtha unui șir (numărul de caractere UTF-16) ca lungime dă rezultate greșite de îndată ce conținutul are chineză sau alt text multi-octet.- Scrierea corpului ca șir în loc de Buffer, astfel încât octeții scriși nu corespund celor declarați.
Toate trei apar înainte de debitare, deci nu se produce niciun cost.
Listă de autoverificare pe partea de client
-
Content-Lengthprovine dinBuffer.byteLength(json, 'utf8')(sauBuffer.from(json).length) — niciodată dinjson.length; - Corpul cererii este scris ca Buffer, nu ca șir;
- Timeout-ul de socket / cerere este ≥ 300 de secunde;
- Când audio-ul depășește aproximativ 8 MB: folosește
file_url(corpul are doar câteva sute de octeți), sau încărcarea multipart dinupload-source, sau treci direct la forma în doi pași; - În cererile multipart, nu seta
Content-Typemanual (lasă clientul să adauge boundary-ul); - Afișează „octeții trimiși efectiv” și compară-i cu
Content-Length; - În forma în doi pași, confirmă că pasul 1 a returnat un
clip_idcustatusfinalizat înainte de a trimite pasul 2.
Greșeli frecvente
| Eroare | Semnificație | Ce să faci |
|---|---|---|
unexpected end of JSON input |
Corpul cererii incomplet (trunchiat) | Parcurge autoverificarea de mai sus sau treci la forma în doi pași |
invalid character '-' in numeric literal |
Un corp multipart a fost trimis către un endpoint JSON | Nu folosi multipart pe endpoint-urile JSON și nu seta Content-Type manual |
one of file_path, file_base64, file_url, or multipart file is required |
Nu s-a furnizat niciun audio | Adaugă file_base64 / file_url / un file multipart |
model is required |
Corpul era JSON valid dar gol (de exemplu {}) |
Trimite cel puțin model |
Invalid request: Invalid request, ... |
Mesaj de ambalaj pentru un corp neanalizabil | Citește a doua jumătate pentru motivul concret (de obicei unul dintre cele de mai sus) |
Endpoint-uri asociate: API-ul de încărcare a audio-ului sursă (pasul 1), API-ul de cover dintr-un clip sursă (pasul 2).
Obține o cheie API
Creează o cheie API în consolă după înregistrare. Fiecare generare costă 0,6 ¥ și returnează 2 piese, descărcările sunt nelimitate și nu este nevoie de număr de telefon.
Obține cheia API Înapoi la prezentare