API för kalibrering av tidsstämplar i låttext
Det här är inte taligenkänning. Texten använder alltid den ursprungliga text du anger; vi placerar bara varje tecken vid rätt tidpunkt — så "felhörda tecken som förskjuter texten" kan aldrig hända.
Beskrivning av ändpunkten
Den linjerar befintlig låttext mot ljud och ger tidsstämplar per rad och per tecken — för teckenvis markering som i karaoke, rullande text och undertextgenerering.
Ändpunkt: POST /api/music/lyrics-align
Autentisering: se Autentisering; headern är Authorization: Bearer YOUR_API_KEY
Fakturering: per anrop (för närvarande 0,10 ¥ per anrop som standard); är röstseparering ikryssad på en plattformslåt debiteras plattformens pris "separera sång/komp" en gång till. Det faktiskt debiterade beloppet följer prisinställningen i backoffice.
Genomsnittlig tid: 5–15 sekunder (beroende på ljudets längd och om sången måste separeras på plats)
Varför kalibrering behövs: tidsstämplarna från genereringssidan är inte alltid exakta
API för tidsstämplad låttext returnerar genereringssidans tidsstämplar per ord direkt, och de är oprecisa:
- repriser, täta harmonier, rap och långa toner driver ofta i sin helhet eller förskjuter enstaka tecken;
- vissa låtar saknar ett stycke i början (till exempel ett rent intro, där första fragmentet börjar först efter ett tiotal sekunder);
- en del rader är svåra att ankra vid en tydlig tidpunkt.
Kalibreringen gör tidslinjeringen på nytt utifrån den text du själv anger: bara tiden korrigeras, aldrig texten — det passar fall där "stämmer det" spelar roll (teckenmarkering som i KTV, undertext per tecken, betyg vid medsjungning).
Rekommenderat tillvägagångssätt (tre steg, bäst resultat)
- Extrahera sången först (separera sång/komp) och linjera bara sångspåret — komp och harmonier stör inte längre. Mätgrund: i en rad-för-rad-jämförelse "fullmix mot sångspår" av samma låt skilde 5 av 28 rader sig mer än 0,25 s (den största 2,64 s); två oberoende motorer skilde sig i snitt 0,239 s på sångspåret och 0,508 s på fullmixen — nästan halva samstämmigheten. För teckenmarkering (KTV/undertext) rekommenderas därför att slå på den. (Den exakta vinsten mäts om med den nya motorn.)
- Ange hela texten: hela låten, rad för rad, ett-till-ett med ljudet. En saknad mening eller sektion förskjuter alla följande rader; skriv inte in tidsstämplar som
[00:23.82]i texten (de ignoreras automatiskt). - På en plattformslåt räcker
vocal_separate: true, och vi gör "separera + linjera" i ett steg.
Tre sätt att använda den
| Sätt | Vad du skickar | Var texten kommer ifrån | Röstseparering |
|---|---|---|---|
| Extern låt · offentlig URL | audio_url + text |
Du anger den | ❌ Stöds inte |
| Extern låt · direkt uppladdning av lokal fil (nytt 2026-10) | audio_object_key + text |
Du anger den | ❌ Stöds inte |
| Plattformslåt (genererad på den här sajten) | song_id |
Vi hämtar den ur låtposten | ✅ Valfritt |
Hur parametrarna hänger ihop (här blir det oftast fel — läs noga)
- Skickar du
song_id→ väg för plattformslåt: skicka inte ocksålyrics/audio_url/audio_object_key; - Skickar du
audio_urlelleraudio_object_key→ väg för extern låt: bara en av dem, och ingensong_id; vocal_separatefungerar bara på plattformslåtar; på en extern låt avvisas den (ljudet finns inte hos oss, det går inte att separera).
Nytt: direkt uppladdning av lokal fil (ljudet går inte via våra servrar)
Används när ljudet finns på din maskin och du inte vill lägga det i din egen offentliga lagring först. Två steg:
POST /api/music/lyrics-align/upload-ticketmedfile_name/file_size/content_typeoch du får enput_url(signerad URL utan långlivade uppgifter) och enobject_key;- Gör en
PUTav filen tillput_urloch ta medcontent_typefrån svaret precis som det är (den ingår i signaturen; ett ändrat tecken ger 403); - Skicka
audio_object_keyi stället föraudio_urlnär du skickar in linjeringen.
Uppgifterna är engångs: när linjeringen är klar (lyckad eller misslyckad) raderar servern objektet, och samma nyckel igen ger ett fel.
Nytt: texten är nu valfri
Tidigare krävde en extern låt text. Nu går det att utelämna den: servern gör först en igenkänning och använder den igenkända texten som låttext.
Priset för det måste sägas rakt ut: texten följer då igenkänningsresultatet, så enstaka tecken kan vara fel. Sådana svar märks med
lyrics_source: "asr", confidence: "low" och i warnings[]
{"code":"no_reference_lyrics"}.
För teckenmarkering / KTV: ange alltid originaltexten.
Begäransparametrar
Headers
| Parameter | Typ | Krävs | Anmärkningar |
|---|---|---|---|
| Authorization | string | ja | Bearer YOUR_API_KEY |
| Content-Type | string | ja | application/json |
Brödtextparametrar
| Parameter | Typ | Krävs | Standard | Anmärkningar |
|---|---|---|---|---|
| song_id | string | en av två | - | ID för plattformslåten |
| lyrics | string | nej | - | Ursprunglig text, rader åtskilda av \n. Kan nu utelämnas |
| audio_url | string | en av två för extern | - | Ljudadress; måste vara offentligt nedladdningsbar |
| audio_object_key | string | en av två för extern | - | Nyckel för det direkt uppladdade objektet (anropa /lyrics-align/upload-ticket först) |
| vocal_separate | boolean | nej | false |
Om sången separeras först (endast plattformslåtar) |
| language | string | nej | automatiskt | Chinese / English m.m.; utan värde gissas det ur texten |
| granularity | string | nej | both |
both / line (ingen utdata per tecken) / word |
| sections | string | nej | keep |
keep behåller markeringar som [Chorus] (de ingår inte i tidslinjen) / drop |
| format | string | nej | json |
json / lrc / lrc-word (de två sista ger även texterna lrc och lrc_word) |
Gränser
| Post | Gräns |
|---|---|
| Ljudets längd | ≤ 6 minuter (längre ger fel och full återbetalning) |
| Ljudets källa | Måste vara offentligt nedladdningsbar; adresser som kräver inloggning accepteras inte |
| Textformat | Ren text, rader med \n; sektionsmarkeringar som [Verse] eller 【主歌】 behålls men ingår inte i tidslinjen |
| Batcher | En låt per anrop; för flera, gör egen loop |
| Spara resultatet | Den här ändpunkten sparar inget; spara resultatet själv |
Exempelbegäranden
Extern låt (text + ljudadress)
curl -X POST https://www.suno-api.io/api/music/lyrics-align \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"lyrics": "Jag går genom kalla gator\nNattvinden stryker mina ögon\nTiden rinner som vatten",
"audio_url": "https://your-bucket.example.com/song.mp3"
}'
Plattformslåt (utan separering)
curl -X POST https://www.suno-api.io/api/music/lyrics-align \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"song_id": "17e52af7-b5df-4877-a98a-dce94e0e6aa2"}'
Plattformslåt + röstseparering (rekommenderas för karaoke)
curl -X POST https://www.suno-api.io/api/music/lyrics-align \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"song_id": "17e52af7-b5df-4877-a98a-dce94e0e6aa2", "vocal_separate": true}'
Svar
Lyckat svar
{
"success": true,
"lyrics_source": "platform",
"vocal_separate": false,
"coverage": 0.935,
"exact": 196,
"fuzzy": 4,
"total": 214,
"lines": [
{
"text": "Jag går genom kalla gator",
"start": 21.66,
"end": 24.06,
"chars": [
{"char": "J", "start": 21.66, "end": 21.74, "word": true},
{"char": "a", "start": 21.98, "end": 22.22, "word": true}
]
}
]
}
Fältförklaring
| Fält | Typ | Anmärkningar |
|---|---|---|
success |
boolean | Om begäran lyckades |
lyrics_source |
string | platform = texten kommer från plattformslåten; user = texten kommer från dig; asr = ingen text angavs och tecknen kommer från igenkänning |
vocal_separate |
boolean | Om röstseparering användes denna gång |
confidence |
string | high / low (alltid low när lyrics_source=asr) |
warnings[] |
array | Meddelanden om försämring; innehåller {"code":"no_reference_lyrics"} utan text |
coverage |
number | Linjeringskvalitet: andel tecken med tydlig tidsankare (0–1) |
exact / fuzzy / total |
number | exakta tecken / homofontecken / giltiga texttecken |
lines[].text |
string | en textrad, tecken för tecken identisk med din originaltext |
lines[].start / end |
number | radens start- och sluttid (sekunder) |
lines[].section |
boolean | om raden är en sektionsmarkering (true = ingen tid, ingen markering) |
lines[].chars[] |
array | tider per tecken: char, start/end i sekunder, word om det ingår i tidslinjen (skiljetecken är false) |
words[] |
array | platt teckenlista: text / start / end / line; ges inte vid granularity=line |
lrc |
string | LRC-text per rad (endast vid format=lrc eller lrc-word) |
lrc_word |
string | utökad tecken-LRC med <mm:ss.xx>-taggar i raden (endast vid format=lrc-word) |
Så används coverage (tre nivåer)
| coverage | Rekommenderad användning |
|---|---|
| ≥ 0,9 | teckenmarkering (karaoke) går bra |
| 0,8 – 0,9 | blanda tecken och hel rad, eller markera bara rader och använd tecknen som riktmärke |
| < 0,8 | endast radmarkering (repriser, täta harmonier, dialekter och rap blir ofta låga) |
Status och tider
| Scenario | Uppmätt tid |
|---|---|
| Plattformslåt · utan separering | cirka 4,5 s |
| Plattformslåt · separering (sångspår finns redan) | cirka 11 s |
| Plattformslåt · separering (måste göras på plats) | cirka 25 s, upp till cirka 1 minut |
| Extern låt · text + ljudadress | cirka 5–15 s (beroende på längd) |
Gränsen för en serverkörning är 8 minuter; ställ in klientens timeout på 120 sekunder eller mer.
Felsvar
{
"success": false,
"message": "音频超过 6 分钟上限(实际 7.2 分钟)"
}
| Scenario | Debiteras? |
|---|---|
| Inget ljud (ingen av de tre) | Debiteras inte (bearbetning startade inte) |
audio_url och audio_object_key samtidigt |
Debiteras inte (bearbetning startade inte) |
| Det direkt uppladdade objektet finns inte än / har raderats | Debiteras inte (bearbetning startade inte) |
Ogiltig granularity / sections / format |
Debiteras inte (bearbetning startade inte) |
| Plattformslåten finns inte / tillhör inte kontot | Debiteras inte (bearbetning startade inte) |
| Parametrar saknas eller är ogiltiga | Debiteras inte (bearbetning startade inte) |
| Ljudet är längre än gränsen på 6 minuter | Full återbetalning |
| Ljudet går inte att ladda ner (inte offentlig adress / kräver inloggning) | Full återbetalning |
| Ingen text angavs och serverns igenkänning misslyckades | Full återbetalning |
| Röstseparering ikryssad men inget användbart sångspår | Full återbetalning (inklusive separeringskostnaden) |
| Fel eller timeout i linjeringstjänsten | Full återbetalning |
Princip: inget slutresultat innebär full återbetalning. Debitering sker först när teckentidsstämplar faktiskt returneras, och återbetalningen är automatisk, utan ansökan.
Fakturering
| Post | När den tas ut | Anmärkningar |
|---|---|---|
| Kalibrering av textens tidsstämplar (bas) | vid varje anrop | per anrop (för närvarande 0,10 ¥ som standard); det faktiska beloppet följer prisinställningen i backoffice |
| Transkriberingstillägg | endast när du inte anger text | servern måste först köra taligenkänning, en kostnad nivån "med text" inte har, därför separat prissatt |
| Röstseparering (valfritt, endast plattformslåtar) | när vocal_separate är ikryssad |
tas ut en gång enligt plattformens gällande pris "separera sång/komp" och görs upp tillsammans med den här ändpunkten |
Kombinationen:
att betala = baspris + (ingen text angiven ? transkriberingstillägg : 0) + (separering ikryssad ? separeringspris : 0)
Röstsepareringen tas bara ut en gång: har du redan separerat låten och sångspåret finns direkt tar den här ändpunkten ut den; måste separeringen ske på plats tar separeringssteget ut den.
Fullständigt exempel (Python)
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://www.suno-api.io"
def align_lyrics(song_id=None, lyrics=None, audio_url=None, vocal_separate=False):
payload = {}
if song_id:
payload["song_id"] = song_id
payload["vocal_separate"] = vocal_separate
else:
payload["lyrics"] = lyrics
payload["audio_url"] = audio_url
r = requests.post(
f"{BASE}/api/music/lyrics-align",
headers={"Authorization": f"Bearer {API_KEY}"},
json=payload,
timeout=600,
)
data = r.json()
if not data.get("success"):
raise RuntimeError(data.get("message"))
return data
res = align_lyrics(song_id="17e52af7-b5df-4877-a98a-dce94e0e6aa2", vocal_separate=True)
print("linjeringskvalitet coverage =", res["coverage"])
for line in res["lines"]:
print(f'{line["start"]:7.2f} {line["text"]}')
# tecken-karaoke: varje tecken i line["chars"] har egen start / end
Vanliga frågor
F: Är utdata per tecken eller per rad?
S: Båda. lines[].start är per rad, lines[].chars[].start / end per tecken; spelaren tar det den behöver.
F: Varför är texten som returneras identisk med det jag skickade? S: Det är avsiktligt. Vi känner inte igen och skriver inte om, vi linjerar bara tiden — texten kan alltså aldrig "rättas till en felstavning".
F: coverage är högt men det låter ändå lite förskjutet.
S: Felet per tecken ligger oftast på några tiotals millisekunder; är hela låten förskjuten ett fast värde finns det troligen en tystnad i början av ljudet — klipp bort den och försök igen.
F: Varför fungerade separeringen nyss men nu står det "sångspåret är inte tillgängligt"? S: Separeringsresultat är kortlivade tillfälliga adresser (mätt: upphör efter ungefär en halvtimme). Då försöker ändpunkten separera igen automatiskt; misslyckas det ändå blir det full återbetalning. Så "separera nu, kalibrera senare" är inte tillförlitligt — gör båda i samma flöde.
F: Måste jag separera en plattformslåt själv först?
S: Nej. Med vocal_separate: true kontrollerar vi om låten redan har ett sångspår; finns inget användbart ger vi fel och återbetalar i stället för att skicka vidare fullmixen.
F: Går det i batcher? S: En låt per begäran. För batcher, loopa; varje anrop debiteras normalt, så cacha resultaten lokalt.
F: Sparas resultatet? S: Den här ändpunkten sparar inget; spara returvärdet själv (rad- och teckentidsstämplar finns i svaret).
Skaffa en API-nyckel
Skapa en API-nyckel i konsolen efter registreringen. Varje generering kostar 0,6 ¥ och returnerar 2 spår, nedladdningar är obegränsade och inget telefonnummer krävs.
Hämta API-nyckel Tillbaka till översikten