API de letras con marcas de tiempo
Descripción del endpoint
Las letras con marcas de tiempo obtienen las marcas de tiempo a nivel de palabra de una canción, para mostrar la letra sincronizada.
Endpoint: POST /api/lyrics/timeline
Facturación: Gratis (consulta de solo lectura; no se cobra nada y no se crea ninguna tarea de generación).
Formato de retorno: se devuelve directamente el array de la línea de tiempo — no hay envoltorio data / success; una vez parseado es simplemente un array.
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 cuerpo
| Parámetro | Tipo | Obligatorio | Por defecto | Notas |
|---|---|---|---|---|
| model | string | no | suno-v6 | Nombre de modelo para el cliente: suno-v6, suno-v6-wild o suno-v6-mini |
| song_id | string | sí | - | ID de la canción |
Ejemplo de petición
curl -X POST https://www.suno-api.io/api/lyrics/timeline \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"song_id": "clip_id"
}'
Respuesta
Abajo hay una respuesta real de producción de una canción de 189,6 segundos en suno-v6 (esa llamada tuvo 69 segmentos; aquí solo se conservan los primeros y los últimos):
[
{
"word": "[Intro]\n\n\n[",
"start_s": 15,
"end_s": 15.04277,
"success": true,
"p_align": 0.99
},
{
"word": "Instrumental: ",
"start_s": 15.04704,
"end_s": 15.10264,
"success": true,
"p_align": 0.99
},
{
"word": "End]\n\n\n",
"start_s": 189.16974,
"end_s": 189.654,
"success": true,
"p_align": 0.99
}
]
Referencia de campos
| Campo | Tipo | Notas |
|---|---|---|
word |
string | El texto de este segmento; incluye sus propios saltos de línea: una línea de letra por segmento con \n al final y \n\n entre párrafos, por lo que aparecen entradas con solo espacios |
start_s |
number | Hora de inicio del segmento en segundos (con decimales) |
end_s |
number | Hora de fin del segmento en segundos. El end_s del último segmento equivale prácticamente a la duración de la canción |
success |
boolean | Si este segmento se alineó correctamente |
p_align |
number | Confianza de la alineación; en las mediciones se mantiene en 0.99 |
Cosas a tener en cuenta
- No busques un envoltorio. La respuesta es el array en sí, no
{"data": ...}, y tampoco tiene camposuccess. - Puede que no haya segmento al principio. En una canción con introducción pura, la medición mostró el primer segmento recién en el segundo 15, y no se garantiza que
start_sempiece en0; para karaoke, gestiona tú mismo el hueco inicial. - También se devuelven marcadores instrumentales y de estructura, con formas como
[Intro],[Verse 1],Instrumental: soft arpeggiating piano, …y[End], igualmente con tiempos palabra por palabra. Antes de montar subtítulos de letra, filtra estos segmentos por el[inicial o porInstrumental; de lo contrario verás descripciones del arreglo como si fueran letra. - Es por palabra, no por línea. La misma línea de letra suele dividirse en varios segmentos y hay que unirlos en líneas por
\n; la hora de una línea es elstart_sde su primer segmento. - El número de segmentos depende de la canción; no asumas una cantidad fija (medido: una canción de 189,6 segundos tenía 69 segmentos y un cuerpo de respuesta de unos 6,5 KB).
Generar un archivo .lrc
Este endpoint solo devuelve datos de la línea de tiempo; no devuelve un archivo directamente. Cuando necesites .lrc, construye las líneas a partir del start_s devuelto en formato [mm:ss.cc] (el campo word incluye sus propios saltos de línea: divide por línea y salta las líneas vacías). Para un ejemplo, consulta «Cómo obtener la letra con marcas de tiempo (.lrc)» en la API de descarga y previsualización de medios de canciones.
Abajo hay una versión completa con filtrado de marcadores instrumentales y de estructura (un segmento por línea, útil para verificar primero la forma de los datos):
import re
SKIP = re.compile(r"^\[.*\]$|^Instrumental:")
def to_lrc(segments):
lines = []
for seg in segments:
if not seg.get("success", True):
continue
text = (seg.get("word") or "").strip()
if not text or SKIP.match(text):
continue
cs = int(max(0.0, float(seg["start_s"])) * 100 + 0.5)
lines.append(f"[{cs // 6000:02d}:{(cs % 6000) // 100:02d}.{cs % 100:02d}]{text}")
return "\n".join(lines)
Notas de compatibilidad
La documentación anterior usaba un ejemplo con el objeto envoltorio { success, song_id, lyrics: [...] }. La documentación actual toma como referencia el array de la línea de tiempo devuelto directamente.
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