Para desarrolladores
Referencia de la API
Cada endpoint, con sus parámetros, los campos que responde y un ejemplo de curl que puedes ejecutar. Búscalo abajo por nombre o ruta; qué significa cada error está en Errores de la API.
Operaciones
POST
/api/assessEvaluar la pronunciación
Envía una grabación y el texto leído; recibe las puntuaciones, cada palabra y cada sonido.
Envío de formulario multipart. Devuelve seis puntuaciones de 0 a 100 (accuracy, native_likeness, completeness, fluency, clarity y speech_rate_ratio), el desglose de cada palabra con cada sonido esperado y oído, y aligned_phonemes: la grabación dividida en sonidos, con sus tiempos, para dibujarla.
Tu clave de API. Obligatoria: una cabecera X-API-Key con la clave de tu consola de operador.
Parámetros
| Nombre | Dónde | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| reference_text | form | string | ✓ | El texto que leyó quien aprende. De 1 a 300 caracteres; un texto hecho solo de espacios se rechaza. |
| language | form | string | ✓ | Idioma del texto, exactamente uno de estos códigos: en-GB, en-US, es-ES, de-DE, fr-FR, it-IT, ca-ES. Las mayúsculas cuentan: en-gb se rechaza con 400 assess.unsupportedLanguage. en-GB es inglés británico, en-US americano. |
| audio | form | file | ✓ | La grabación. Lo mejor es WAV (16 kHz, 16 bits, mono); otros formatos como WebM u OGG se convierten. Los envíos de más de 1 MB aproximadamente reciben HTTP 413, y solo se evalúan los primeros 15 segundos de una grabación. |
| X-API-Key | header | <customer key> | ✓ | Tu clave de API de la consola de operador. |
Respuesta
| Campo | Tipo | Descripción |
|---|---|---|
| accuracy | number (0–100) | Lo bien que los sonidos coincidieron con los esperados. |
| native_likeness | number (0–100) | Proporción de los sonidos esperados dichos como los dicen los nativos, con todo detalle; un sonido correcto sin el detalle nativo cuenta en accuracy, no aquí. |
| completeness | number (0–100) | Proporción de los sonidos esperados que se dijeron. |
| fluency | number (0–100) | Habla regular sin pausas largas, ponderada por la precisión. |
| clarity | number (0–100) | Claridad: con qué claridad lo entendería quien escucha. |
| speech_rate_ratio | number (0–100) | Proporción del tiempo entre el primer y el último sonido dedicada a hablar en vez de a hacer pausas. |
| duration | number (s) | Duración de la grabación en segundos. |
| analyzed_text | object[] | Una entrada por palabra del texto, con los campos de abajo. |
| analyzed_text[].word | string | La palabra tal como está escrita en reference_text. |
| analyzed_text[].accuracy, clarity | number (0–100) | La precisión y la claridad de la propia palabra. |
| analyzed_text[].start_time, end_time | number (s) | null | Inicio y fin en segundos desde el principio de la grabación; null si no se oyó. |
| analyzed_text[].user_audio_base64 | string (base64 WAV) | null | La grabación de esta palabra, en WAV base64; null si no se oyó. |
| analyzed_text[].grapheme_to_phoneme | object[] | Qué letras forman cada sonido: para cada phoneme_index, los graphemes (posiciones de las letras en la palabra). |
| analyzed_text[].phoneme_details | object[] | Una entrada por sonido esperado, y por sonido de más que se oyó, con los campos de abajo. |
| analyzed_text[].phoneme_details[].phoneme | string | El sonido esperado en AFI; vacío para un sonido de más. |
| analyzed_text[].phoneme_details[].predicted | string | El sonido que se oyó, en AFI; vacío ("") si se omitió. |
| analyzed_text[].phoneme_details[].confidence | number (0–1) | Lo seguro que está el modelo del sonido oído, de 0 a 1. |
| analyzed_text[].phoneme_details[].is_insertion | boolean | Un sonido de más que el texto no tiene. |
| analyzed_text[].phoneme_details[].is_close | boolean | Un sonido equivocado, pero cercano al esperado. |
| analyzed_text[].phoneme_details[].is_reference | boolean | El sonido es del texto (false para un sonido de más). |
| analyzed_text[].phoneme_details[].expected_phone, heard_phone | string | null | El sonido esperado y el oído con el detalle que les dan los nativos, p. ej. tʰ o d̪; null si no lo hay. |
| analyzed_text[].phoneme_details[].detail_off | boolean | true cuando el sonido correcto se dijo sin su detalle nativo (t por tʰ): cuenta en accuracy pero no en native_likeness. |
| analyzed_text[].phoneme_details[].user_audio_base64 | string (base64 WAV) | null | La grabación de este sonido, en WAV base64; null si no tiene tiempos. |
| analyzed_text[].phoneme_details[].start_time, end_time | number (s) | null | Inicio y fin en segundos desde el principio de la grabación; null si no se oyó. |
| aligned_phonemes | object[] | La grabación como secuencia de sonidos: symbol, start, end, duration, word_start, los candidates más probables y un fragmento. |
| waveform | number[] | Muestras de amplitud para dibujar la grabación. |
| processed_audio_base64 | string (base64 WAV) | La grabación limpia que se evaluó. |
Ejemplo de petición
curl
curl https://spelly.ch/api/assess \
-H 'X-API-Key: YOUR_KEY' \
-F 'reference_text=The weather is lovely' \
-F language=en-GB \
-F audio=@recording.wavEjemplo de respuesta
JSON
{
"accuracy": 100,
"native_likeness": 92,
"completeness": 100,
"fluency": 100,
"clarity": 98,
"speech_rate_ratio": 100.0,
"analyzed_text": [
{
"word": "the",
"accuracy": 100.0,
"clarity": 97.93445765972137,
"phoneme_details": [
{
"phoneme": "ð",
"predicted": "ð",
"confidence": 0.9709068536758423,
"is_insertion": false,
"is_close": false,
"is_reference": true,
"expected_phone": "ð",
"heard_phone": "ð",
"detail_off": false,
"user_audio_base64": "UklGRo…",
"start_time": 0.042020833333333334,
"end_time": 0.10505208333333334
},
{
"phoneme": "ə",
"predicted": "ə",
"confidence": 0.9877822995185852,
"is_insertion": false,
"is_close": false,
"is_reference": true,
"expected_phone": "ə",
"heard_phone": "ə",
"detail_off": false,
"user_audio_base64": "UklGRi…",
"start_time": 0.08404166666666667,
"end_time": 0.16808333333333333
}
],
"start_time": 0.042020833333333334,
"end_time": 0.16808333333333333,
"user_audio_base64": "UklGRu…",
"grapheme_to_phoneme": [
{
"graphemes": [
0,
1,
2
],
"phoneme_index": 0
},
{
"graphemes": [
0,
1,
2
],
"phoneme_index": 1
}
]
}
],
"waveform": [
0.00019696683739311993,
-0.00015526238712482154,
-0.00024423340801149607,
1.6281235730275512e-05
],
"duration": 1.387,
"aligned_phonemes": [
{
"index": 0,
"start": 0.042020833333333334,
"duration": 0.06303125000000001,
"end": 0.10505208333333334,
"symbol": "ð",
"word_start": false,
"candidates": [
{
"symbol": "ð",
"confidence": 0.8176507949829102
}
],
"user_audio_base64": "UklGRo…"
},
{
"index": 1,
"start": 0.08404166666666667,
"duration": 0.08404166666666667,
"end": 0.16808333333333333,
"symbol": "ə",
"word_start": false,
"candidates": [
{
"symbol": "ə",
"confidence": 0.9877822995185852
}
],
"user_audio_base64": "UklGRi…"
}
],
"processed_audio_base64": "UklGRn…"
}Notas
- El audio de ejemplo para el mismo texto viene de /api/assess/synthesize, que puedes llamar a la vez.