API de calibración de marcas de tiempo de la letra

Actualizado el 2026-09-18 · equipo de Suno-API

Esto no es reconocimiento de voz. El texto usa siempre la letra original que tú aportas; nosotros solo colocamos cada carácter en el instante correcto — así nunca ocurre eso de "caracteres mal oídos que descuadran la letra".

Descripción del endpoint

Alinea una letra existente con un audio y devuelve marcas de tiempo por línea y por carácter, para resaltado carácter a carácter tipo karaoke, letra con desplazamiento y generación de subtítulos.

Endpoint: POST /api/music/lyrics-align

Autenticación: consulta Autenticación; la cabecera es Authorization: Bearer YOUR_API_KEY

Facturación: se cobra por llamada (actualmente 0,1 ¥ por llamada por defecto); si en una canción de la plataforma marcas la separación de voz, se cobra una vez más al precio de "separación de voz/acompañamiento". El importe realmente cobrado sigue la configuración de precios del back-office.

Tiempo medio: 5–15 segundos (según la duración del audio y si hay que separar la voz al momento)

Por qué hace falta calibrar: las marcas del lado generador no siempre son exactas

La API de letras con marcas de tiempo devuelve directamente las marcas palabra a palabra del lado generador y tienen imprecisiones:

La calibración rehace la alineación temporal sobre la letra que tú aportas: solo se corrige el tiempo, nunca el texto, lo que encaja en casos donde importa que "cuadre" (resaltado por carácter tipo KTV, subtítulos por carácter, puntuación de canto).

Enfoque recomendado (tres pasos, mejor resultado)

  1. Extrae primero la voz (separación voz/acompañamiento) y alinea solo la pista de voz: el acompañamiento y las armonías dejan de interferir. Base medida: en una comparación línea a línea de "mezcla completa vs pista de voz" de la misma canción, 5 de 28 líneas diferían más de 0,25 s (la mayor, 2,64 s); dos motores independientes diferían de media 0,239 s en la pista de voz y 0,508 s en la mezcla completa — casi la mitad de concordancia. Por eso, para resaltado por carácter (KTV/subtítulos) se recomienda activarlo. (La mejora exacta se está midiendo de nuevo con el motor nuevo.)
  2. Aporta la letra completa: la canción entera, línea a línea, correspondiendo uno a uno con el audio. Si falta una frase o una sección, todas las líneas posteriores se desplazan; no incluyas marcas como [00:23.82] en la letra (se ignoran automáticamente).
  3. En una canción de la plataforma basta con marcar vocal_separate: true y hacemos "separación + alineación" en un solo paso.

Tres formas de usarlo

Uso Qué envías De dónde sale la letra Separación de voz
Canción externa · URL pública audio_url + letra La aportas tú ❌ No admitido
Canción externa · subida directa de un archivo local (nuevo en 2026-10) audio_object_key + letra La aportas tú ❌ No admitido
Canción de la plataforma (generada en este sitio) song_id La tomamos del registro de la canción ✅ Opcional

Cómo se relacionan los parámetros (es lo que más se falla: léelo con atención)

Nuevo: subida directa de un archivo local (el audio no pasa por nuestros servidores)

Úsalo cuando el audio está en tu máquina y prefieres no subirlo antes a tu propio almacenamiento público. Dos pasos:

  1. POST /api/music/lyrics-align/upload-ticket con file_name / file_size / content_type y recibes una put_url (URL firmada, sin credenciales de larga vida) y un object_key;
  2. Haz PUT del archivo a put_url, llevando el content_type de la respuesta tal cual (participa en la firma; un carácter cambiado devuelve 403);
  3. Al enviar la alineación, manda audio_object_key en lugar de audio_url.

La credencial es de un solo uso: al terminar la alineación (éxito o fallo) el servidor borra el objeto y reutilizar la misma clave da error.

Nuevo: la letra ahora es opcional

Antes una canción externa exigía letra. Ahora puedes omitirla: el servidor hace un reconocimiento y usa el texto reconocido como letra.

Hay que decirlo con claridad: el texto pasa a depender del resultado del reconocimiento, así que algún carácter puede ser incorrecto. Esas respuestas se marcan con lyrics_source: "asr", confidence: "low" y, en warnings[], {"code":"no_reference_lyrics"}.

Para resaltado por carácter / KTV, aporta siempre la letra original.

Parámetros de la petición

Headers

Parámetro Tipo Obligatorio Notas
Authorization string sí Bearer YOUR_API_KEY
Content-Type string sí application/json

Parámetros del body

Parámetro Tipo Obligatorio Por defecto Notas
song_id string uno de dos - ID de canción de la plataforma
lyrics string no - Letra original, líneas separadas por \n. Ahora puede omitirse
audio_url string uno de dos para externas - Dirección del audio; debe ser descargable públicamente
audio_object_key string uno de dos para externas - Clave del objeto subido directamente (llama antes a /lyrics-align/upload-ticket)
vocal_separate boolean no false Si separar la voz primero (solo canciones de la plataforma)
language string no automático Chinese / English, etc.; si no se envía se deduce de la letra
granularity string no both both / line (sin salida por carácter) / word
sections string no keep keep conserva marcas como [Chorus] (no entran en la línea de tiempo) / drop
format string no json json / lrc / lrc-word (los dos últimos devuelven también el texto lrc y lrc_word)

Límites

Elemento Límite
Duración del audio ≤ 6 minutos (más devuelve error y reembolso completo)
Origen del audio Debe ser descargable públicamente; no se aceptan direcciones que requieran sesión
Formato de la letra Texto plano, líneas con \n; las marcas de sección como [Verse] o 【主歌】 se conservan tal cual pero no entran en la línea de tiempo
Lotes Una canción por llamada; para varias, haz tu propio bucle
Guardado del resultado Este endpoint no persiste nada; guarda tú el resultado

Ejemplos de petición

Canción externa (letra + dirección del 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": "Caminando por calles frías\nLa brisa nocturna roza mis ojos\nEl tiempo fluye como el agua",
    "audio_url": "https://your-bucket.example.com/song.mp3"
  }'

Canción de la plataforma (sin separación)

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"}'

Canción de la plataforma + separación de voz (recomendado para 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}'

Respuesta

Respuesta correcta

{
  "success": true,
  "lyrics_source": "platform",
  "vocal_separate": false,
  "coverage": 0.935,
  "exact": 196,
  "fuzzy": 4,
  "total": 214,
  "lines": [
    {
      "text": "Caminando por calles frías",
      "start": 21.66,
      "end": 24.06,
      "chars": [
        {"char": "C", "start": 21.66, "end": 21.74, "word": true},
        {"char": "a", "start": 21.98, "end": 22.22, "word": true}
      ]
    }
  ]
}

Referencia de campos

Campo Tipo Notas
success boolean Si la petición tuvo éxito
lyrics_source string platform = letra tomada de la canción de la plataforma; user = letra aportada por ti; asr = no diste letra y el texto vino del reconocimiento
vocal_separate boolean Si esta vez pasó por separación de voz
confidence string high / low (siempre low cuando lyrics_source=asr)
warnings[] array Avisos de degradación; contiene {"code":"no_reference_lyrics"} cuando no hubo letra
coverage number Calidad de la alineación: proporción de caracteres con ancla temporal clara (0–1)
exact / fuzzy / total number Caracteres exactos / homófonos / caracteres válidos de la letra
lines[].text string Una línea de letra, carácter a carácter igual a tu original
lines[].start / end number Inicio y fin de la línea (segundos)
lines[].section boolean Si la línea es una marca de sección (true = sin tiempo y sin resaltado)
lines[].chars[] array Tiempos por carácter: char, start/end en segundos, word si entra en la línea de tiempo (la puntuación es false)
words[] array Lista plana por carácter: text / start / end / line; no se devuelve con granularity=line
lrc string Texto LRC por línea (solo con format=lrc o lrc-word)
lrc_word string LRC por carácter mejorado, con etiquetas <mm:ss.xx> en línea (solo con format=lrc-word)

Cómo usar coverage (tres tramos)

coverage Uso sugerido
≥ 0,9 Sirve para resaltado por carácter (karaoke)
0,8 – 0,9 Mezcla por carácter y por línea, o resalta solo líneas y usa el carácter como referencia
< 0,8 Solo resaltado por línea (repeticiones, armonías densas, dialectos y rap tienden a salir bajos)

Estado y tiempos

Escenario Tiempo medido
Canción de plataforma · sin separación unos 4,5 s
Canción de plataforma · separación (ya hay pista de voz) unos 11 s
Canción de plataforma · separación (hay que separar al momento) unos 25 s, hasta 1 minuto
Canción externa · letra + dirección del audio unos 5–15 s (según la duración)

El límite de una ejecución en el servidor es 8 minutos; configura el timeout del cliente en 120 segundos o más.

Respuestas de error

{
  "success": false,
  "message": "音频超过 6 分钟上限(实际 7.2 分钟)"
}
Escenario ¿Se cobra?
Falta el audio (no se envía ninguno de los tres) No se cobra (no se inició el proceso)
audio_url y audio_object_key a la vez No se cobra (no se inició el proceso)
El objeto subido aún no está o ya se borró No se cobra (no se inició el proceso)
granularity / sections / format inválidos No se cobra (no se inició el proceso)
La canción de la plataforma no existe / no es de la cuenta actual No se cobra (no se inició el proceso)
Parámetros ausentes o inválidos No se cobra (no se inició el proceso)
Audio por encima del límite de 6 minutos Reembolso completo
Audio no descargable (dirección no pública / requiere login) Reembolso completo
Sin letra y el reconocimiento del servidor falló Reembolso completo
Marcaste separación de voz pero no hay pista usable Reembolso completo (incluye el precio de la separación)
Fallo o timeout del servicio de alineación Reembolso completo

Principio: sin resultado final, reembolso completo. Solo se cobra cuando realmente se devuelven las marcas por carácter, y el reembolso es automático, sin solicitud.

Facturación

Concepto Cuándo se cobra Notas
Calibración de marcas de la letra (base) En cada llamada Por llamada (actualmente 0,1 ¥ por llamada por defecto); el importe real sigue la configuración de precios del back-office
Recargo por transcripción Solo si no aportas letra El servidor debe ejecutar un reconocimiento de voz, un coste que el tramo "con letra" no tiene, así que se tarifa aparte
Separación de voz (opcional, solo canciones de la plataforma) Al marcar vocal_separate Se cobra una vez al precio actual de "separación de voz/acompañamiento" y se liquida junto con este endpoint

La combinación:

a pagar = precio base + (¿sin letra? recargo por transcripción : 0) + (¿separación marcada? precio de separación : 0)

La separación de voz se cobra una sola vez: si ya separaste y tienes la pista de voz disponible, la cobra este endpoint; si hay que separar al momento, la cobra el paso de separación.

Ejemplo completo (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("calidad de alineación coverage =", res["coverage"])
for line in res["lines"]:
    print(f'{line["start"]:7.2f}  {line["text"]}')
    # karaoke por carácter: cada carácter en line["chars"] tiene su start / end

Preguntas frecuentes

P: ¿La salida es por carácter o por línea? R: Las dos. lines[].start es por línea y lines[].chars[].start / end por carácter; el reproductor usa la que necesite.

P: ¿Por qué el texto devuelto es idéntico al que envié? R: Es el diseño. No reconocemos ni reescribimos, solo alineamos tiempos, así que la letra nunca se "corrige a errata".

P: El coverage es alto pero aún suena algo desviado. R: El error por carácter suele estar en decenas de milisegundos; si toda la canción va desviada una cantidad fija, lo más probable es que haya un tramo de silencio al principio del audio: recórtalo y vuelve a probar.

P: ¿Por qué hace un momento servía la separación y ahora dice "pista de voz no disponible"? R: Los resultados de separación son direcciones temporales de vida corta (medido: caducan a la media hora aproximadamente). En ese caso el endpoint intenta separar de nuevo; si aun así falla, hay reembolso completo. Así que "separar ahora y calibrar luego" no es fiable: hazlo dentro del mismo flujo.

P: ¿Tengo que separar yo una canción de la plataforma? R: No. Con vocal_separate: true comprobamos si la canción ya tiene pista de voz; si no hay una usable, da error y reembolsa en lugar de pasar la mezcla completa.

P: ¿Se pueden hacer lotes? R: Una canción por petición. Para lotes, haz un bucle; cada llamada se cobra con normalidad, así que se recomienda cachear los resultados.

P: ¿Se guarda el resultado? R: Este endpoint no persiste nada; guarda tú el valor devuelto (las marcas por línea y por carácter van en la respuesta).

SiguienteAPI de certificado de licencia comercial de música

Obtener una clave de API

Crea una clave de API en la consola después de registrarte. Cada generación cuesta 0,6 ¥ y devuelve 2 pistas, las descargas son ilimitadas y no hace falta número de teléfono.

Obtener clave de API Volver al resumen