API de calibrage des horodatages des paroles
Ce n'est pas de la reconnaissance vocale. Le texte reprend toujours les paroles d'origine que vous fournissez ; nous ne faisons que placer chaque caractère au bon instant — vous n'aurez donc jamais de « paroles décalées à cause de caractères mal reconnus ».
Description du point d'accès
Il aligne des paroles existantes sur un audio et renvoie des horodatages par ligne et par caractère, pour le surlignage caractère par caractère type karaoké, les paroles défilantes et la génération de sous-titres.
Point d'accès : POST /api/music/lyrics-align
Authentification : voir Authentification ; l'en-tête est Authorization: Bearer YOUR_API_KEY
Facturation : facturé à l'appel (actuellement 0,1 ¥ par appel par défaut) ; sur un morceau de la plateforme avec séparation de la voix cochée, le tarif « séparation voix/accompagnement » de la plateforme est facturé une fois de plus. Le montant réellement facturé suit la configuration tarifaire du back-office.
Durée moyenne : 5 à 15 secondes (selon la longueur de l'audio et la nécessité de séparer la voix sur place)
Pourquoi calibrer : les horodatages du côté génération ne sont pas toujours exacts
L'API de paroles horodatées renvoie directement les horodatages mot par mot du côté génération, et ils comportent des imprécisions :
- les reprises, les harmonies denses, le rap et les notes tenues dérivent souvent globalement ou décalent des caractères isolés ;
- certains morceaux perdent un passage au début (par exemple une intro pure, avec le premier fragment qui ne commence qu'à la quinzaine de secondes) ;
- certaines lignes sont difficiles à rattacher à un instant précis.
Le calibrage refait l'alignement temporel sur les paroles que vous fournissez : seul le temps est corrigé, jamais le texte, ce qui convient aux cas où « est-ce que ça tombe juste » compte (surlignage par caractère type KTV, sous-titres par caractère, notation de chant).
Approche recommandée (trois étapes, meilleur résultat)
- Extrayez d'abord la voix (séparation voix/accompagnement) et n'alignez que la piste de voix — l'accompagnement et les harmonies cessent de perturber. Base mesurée : dans une comparaison ligne à ligne « mixage complet vs piste de voix » du même morceau, 5 lignes sur 28 différaient de plus de 0,25 s (la plus grande de 2,64 s) ; deux moteurs indépendants différaient en moyenne de 0,239 s sur la piste de voix et de 0,508 s sur le mixage complet — presque deux fois moins de concordance. Pour un surlignage par caractère (KTV/sous-titres), il est donc conseillé de l'activer. (Le gain exact est en cours de remesure avec le nouveau moteur.)
- Fournissez les paroles complètes : tout le morceau, ligne par ligne, en correspondance une à une avec l'audio. Une phrase ou une section manquante décale toutes les lignes suivantes ; n'incluez pas d'horodatages comme
[00:23.82]dans les paroles (ils sont ignorés automatiquement). - Sur un morceau de la plateforme, il suffit de cocher
vocal_separate: trueet nous faisons « séparation + alignement » en une seule étape.
Trois façons d'utiliser l'API
| Usage | Ce que vous envoyez | D'où viennent les paroles | Séparation de la voix |
|---|---|---|---|
| Morceau externe · URL publique | audio_url + paroles |
Vous les fournissez | ❌ Non pris en charge |
| Morceau externe · envoi direct d'un fichier local (nouveau 2026-10) | audio_object_key + paroles |
Vous les fournissez | ❌ Non pris en charge |
| Morceau de la plateforme (généré sur ce site) | song_id |
Nous les prenons dans la fiche du morceau | ✅ Optionnel |
Relations entre les paramètres (c'est là qu'on se trompe le plus, à lire attentivement)
- Envoyer
song_id→ voie morceau de la plateforme : n'envoyez pas en pluslyrics/audio_url/audio_object_key; - Envoyer
audio_urlouaudio_object_key→ voie morceau externe : un seul des deux, et n'envoyez passong_id; vocal_separatene fonctionne que pour les morceaux de la plateforme ; l'envoyer pour un morceau externe est refusé (l'audio n'est pas chez nous, il ne peut pas être séparé).
Nouveau : envoi direct d'un fichier local (l'audio ne passe pas par nos serveurs)
À utiliser quand l'audio est sur votre machine et que vous préférez ne pas le déposer d'abord dans votre propre stockage public. Deux étapes :
POST /api/music/lyrics-align/upload-ticketavecfile_name/file_size/content_typeet vous recevez uneput_url(URL signée, sans identifiant longue durée) et unobject_key;- Faites un
PUTdu fichier versput_url, en portant lecontent_typede la réponse tel quel (il participe à la signature ; un caractère modifié donne 403) ; - Lors de l'envoi de l'alignement, transmettez
audio_object_keyau lieu deaudio_url.
L'identifiant est à usage unique : une fois l'alignement terminé (succès ou échec) le serveur supprime l'objet, et réutiliser la même clé renvoie une erreur.
Nouveau : les paroles sont devenues facultatives
Avant, un morceau externe exigeait des paroles. Désormais vous pouvez les omettre : le serveur fait une reconnaissance et utilise le texte reconnu comme paroles.
Le compromis doit être dit clairement : le texte dépend alors du résultat de la reconnaissance, donc des caractères peuvent être faux. Ces réponses sont marquées
lyrics_source: "asr", confidence: "low" et, dans warnings[],
{"code":"no_reference_lyrics"}.
Pour un surlignage par caractère / KTV, fournissez toujours les paroles d'origine.
Paramètres de la requête
Headers
| Paramètre | Type | Obligatoire | Remarques |
|---|---|---|---|
| Authorization | string | oui | Bearer YOUR_API_KEY |
| Content-Type | string | oui | application/json |
Paramètres du body
| Paramètre | Type | Obligatoire | Par défaut | Remarques |
|---|---|---|---|---|
| song_id | string | l'un des deux | - | ID de morceau de la plateforme |
| lyrics | string | non | - | Paroles d'origine, lignes séparées par \n. Peut maintenant être omis |
| audio_url | string | l'un des deux pour l'externe | - | Adresse de l'audio ; doit être téléchargeable publiquement |
| audio_object_key | string | l'un des deux pour l'externe | - | Clé de l'objet envoyé directement (appelez d'abord /lyrics-align/upload-ticket) |
| vocal_separate | boolean | non | false |
Séparer la voix d'abord (morceaux de la plateforme uniquement) |
| language | string | non | détection auto | Chinese / English, etc. ; si absent, déduit des paroles |
| granularity | string | non | both |
both / line (pas de sortie par caractère) / word |
| sections | string | non | keep |
keep conserve les marqueurs comme [Chorus] (ils n'entrent pas dans la timeline) / drop |
| format | string | non | json |
json / lrc / lrc-word (les deux derniers renvoient aussi les textes lrc et lrc_word) |
Limites
| Élément | Limite |
|---|---|
| Durée de l'audio | ≤ 6 minutes (au-delà, erreur et remboursement intégral) |
| Source de l'audio | Doit être téléchargeable publiquement ; les adresses exigeant une session ne sont pas acceptées |
| Format des paroles | Texte brut, lignes séparées par \n ; les marqueurs de section comme [Verse] ou 【主歌】 sont conservés tels quels mais n'entrent pas dans la timeline |
| Lots | Un morceau par appel ; pour plusieurs, faites votre propre boucle |
| Conservation du résultat | Ce point d'accès ne persiste rien ; conservez vous-même le résultat |
Exemples de requête
Morceau externe (paroles + adresse de l'audio)
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": "Je marche dans les rues froides\nLa brise du soir effleure mes yeux\nLe temps coule comme l'\''eau",
"audio_url": "https://your-bucket.example.com/song.mp3"
}'
Morceau de la plateforme (sans séparation)
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"}'
Morceau de la plateforme + séparation de la voix (recommandé pour le karaoké)
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}'
Réponse
Réponse de succès
{
"success": true,
"lyrics_source": "platform",
"vocal_separate": false,
"coverage": 0.935,
"exact": 196,
"fuzzy": 4,
"total": 214,
"lines": [
{
"text": "Je marche dans les rues froides",
"start": 21.66,
"end": 24.06,
"chars": [
{"char": "J", "start": 21.66, "end": 21.74, "word": true},
{"char": "e", "start": 21.98, "end": 22.22, "word": true}
]
}
]
}
Référence des champs
| Champ | Type | Remarques |
|---|---|---|
success |
boolean | Si la requête a réussi |
lyrics_source |
string | platform = paroles prises dans le morceau de la plateforme ; user = paroles fournies par vous ; asr = vous n'avez pas fourni de paroles et le texte vient de la reconnaissance |
vocal_separate |
boolean | Si la séparation de la voix a été utilisée cette fois |
confidence |
string | high / low (toujours low quand lyrics_source=asr) |
warnings[] |
array | Avis de dégradation ; contient {"code":"no_reference_lyrics"} en l'absence de paroles |
coverage |
number | Qualité de l'alignement : part des caractères ayant une ancre temporelle claire (0–1) |
exact / fuzzy / total |
number | Caractères exacts / homophones / caractères valides des paroles |
lines[].text |
string | Une ligne de paroles, caractère pour caractère identique à votre original |
lines[].start / end |
number | Début et fin de la ligne (secondes) |
lines[].section |
boolean | Si la ligne est un marqueur de section (true = pas de temps, pas de surlignage) |
lines[].chars[] |
array | Temps par caractère : char, start/end en secondes, word s'il compte dans la timeline (la ponctuation vaut false) |
words[] |
array | Liste plate par caractère : text / start / end / line ; non renvoyée avec granularity=line |
lrc |
string | Texte LRC par ligne (uniquement avec format=lrc ou lrc-word) |
lrc_word |
string | LRC par caractère enrichi, avec balises <mm:ss.xx> en ligne (uniquement avec format=lrc-word) |
Comment utiliser coverage (trois paliers)
| coverage | Usage conseillé |
|---|---|
| ≥ 0,9 | Surlignage par caractère (karaoké) possible |
| 0,8 – 0,9 | Mélange par caractère et par ligne, ou surlignage des lignes seules avec le caractère en indicatif |
| < 0,8 | Surlignage par ligne uniquement (reprises, harmonies denses, dialectes et rap sortent souvent bas) |
État et durées
| Scénario | Durée mesurée |
|---|---|
| Morceau de la plateforme · sans séparation | environ 4,5 s |
| Morceau de la plateforme · séparation (piste de voix déjà présente) | environ 11 s |
| Morceau de la plateforme · séparation (à faire sur place) | environ 25 s, jusqu'à environ 1 minute |
| Morceau externe · paroles + adresse de l'audio | environ 5–15 s (selon la longueur) |
La limite d'une exécution côté serveur est de 8 minutes ; réglez le timeout du client à 120 secondes ou plus.
Réponses d'erreur
{
"success": false,
"message": "音频超过 6 分钟上限(实际 7.2 分钟)"
}
| Scénario | Facturé ? |
|---|---|
| Audio manquant (aucun des trois) | Non facturé (traitement non démarré) |
audio_url et audio_object_key en même temps |
Non facturé (traitement non démarré) |
| L'objet envoyé directement n'est pas encore là / a été supprimé | Non facturé (traitement non démarré) |
granularity / sections / format invalide |
Non facturé (traitement non démarré) |
| Le morceau de la plateforme n'existe pas / n'appartient pas au compte | Non facturé (traitement non démarré) |
| Paramètres manquants ou invalides | Non facturé (traitement non démarré) |
| Audio au-delà de la limite de 6 minutes | Remboursement intégral |
| Audio non téléchargeable (adresse non publique / connexion requise) | Remboursement intégral |
| Pas de paroles et échec de la reconnaissance côté serveur | Remboursement intégral |
| Séparation de la voix cochée mais aucune piste utilisable | Remboursement intégral (frais de séparation compris) |
| Anomalie ou timeout du service d'alignement | Remboursement intégral |
Principe : pas de résultat final, remboursement intégral. La facturation n'intervient que si les horodatages par caractère sont réellement renvoyés, et le remboursement est automatique, sans demande.
Facturation
| Élément | Quand c'est facturé | Remarques |
|---|---|---|
| Calibrage des horodatages (base) | À chaque appel | À l'appel (actuellement 0,1 ¥ par appel par défaut) ; le montant réel suit la configuration tarifaire du back-office |
| Supplément de transcription | Uniquement si vous ne fournissez pas de paroles | Le serveur doit lancer une reconnaissance vocale, un coût que le palier « avec paroles » n'a pas, d'où une tarification séparée |
| Séparation de la voix (optionnelle, morceaux de la plateforme uniquement) | Quand vocal_separate est coché |
Facturée une fois au tarif actuel « séparation voix/accompagnement » et réglée avec ce point d'accès |
La combinaison :
à payer = prix de base + (pas de paroles ? supplément de transcription : 0) + (séparation cochée ? prix de la séparation : 0)
La séparation de la voix n'est facturée qu'une fois : si vous avez déjà séparé le morceau et que la piste de voix est disponible, c'est ce point d'accès qui la facture ; si la séparation doit se faire sur place, c'est l'étape de séparation qui la facture.
Exemple complet (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("qualité d'alignement coverage =", res["coverage"])
for line in res["lines"]:
print(f'{line["start"]:7.2f} {line["text"]}')
# karaoké par caractère : chaque caractère de line["chars"] a son propre start / end
Questions fréquentes
Q : La sortie est-elle par caractère ou par ligne ?
R : Les deux. lines[].start est par ligne, lines[].chars[].start / end par caractère ; le lecteur prend ce dont il a besoin.
Q : Pourquoi le texte renvoyé est-il identique à ce que j'ai envoyé ? R : C'est voulu. Nous ne reconnaissons ni ne réécrivons, nous ne faisons qu'aligner le temps : les paroles ne peuvent donc jamais être « corrigées en faute ».
Q : Le coverage est élevé mais ça sonne encore un peu décalé.
R : L'erreur par caractère est généralement de l'ordre de quelques dizaines de millisecondes ; si tout le morceau est décalé d'une valeur fixe, c'est probablement un passage de silence au début de l'audio : coupez-le et réessayez.
Q : La séparation fonctionnait il y a un instant, et maintenant elle dit « piste de voix indisponible ». R : Les résultats de séparation sont des adresses temporaires de courte durée (mesuré : expiration au bout d'une demi-heure environ). Le point d'accès tente alors de reséparer automatiquement ; si cela échoue encore, c'est remboursement intégral. Donc « séparer maintenant, calibrer plus tard » n'est pas fiable : faites les deux dans le même flux.
Q : Dois-je séparer moi-même un morceau de la plateforme ?
R : Non. Avec vocal_separate: true, nous vérifions si le morceau a déjà une piste de voix ; s'il n'y en a pas d'utilisable, nous renvoyons une erreur et remboursons plutôt que de faire passer le mixage complet.
Q : Peut-on faire des lots ? R : Un morceau par requête. Pour des lots, bouclez ; chaque appel est facturé normalement, il est donc conseillé de mettre les résultats en cache.
Q : Le résultat est-il conservé ? R : Ce point d'accès ne persiste rien ; conservez vous-même la valeur renvoyée (les horodatages par ligne et par caractère sont dans la réponse).
Obtenir une clé d'API
Créez une clé d'API dans la console après votre inscription. Chaque génération coûte 0,6 ¥ et renvoie 2 pistes, les téléchargements sont illimités et aucun numéro de téléphone n'est requis.
Obtenir une clé d'API Retour à la présentation