# Transcribe audio y video

> Sube un audio o video, transcríbelo con tiempo por frase y, si quieres, quién habla. Descarga en JSON, SRT, VTT o texto.

La transcripción es independiente del clipping: sirve para un podcast, una clase, una entrevista o cualquier archivo de audio o video. El resultado viene en frases con inicio y fin en segundos.

### Pide la URL de subida

```bash
curl -X POST https://api.cut.pro/api/v1/transcriptions/upload \
  -H "X-Api-Key: $CUTPRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "file_name": "entrevista.mp3", "file_size": 48210000, "content_type": "audio/mpeg" }'
```

```json title="200 OK"
{ "media_id": "7412950033118822", "kind": "audio", "upload_url": "https://...", "expires_in": 3600 }
```

La extensión de `file_name` decide si es audio o video. El tope es el menor entre el límite de subida del plan y el espacio libre en el storage.

### Envía el archivo

```bash
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: audio/mpeg" \
  --upload-file entrevista.mp3
```

El `Content-Type` debe ser el mismo del paso anterior.

### Transcribe

```bash
curl -X POST https://api.cut.pro/api/v1/transcriptions \
  -H "X-Api-Key: $CUTPRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "media_id": "7412950033118822",
    "file_name": "entrevista.mp3",
    "file_size": 48210000,
    "source_language": "pt",
    "speaker_labels": true
  }'
```

```json title="202 Accepted"
{ "id": "7412950040021177", "status": "processing", "credits_charged": 42 }
```

| Campo | Descripción |
|---|---|
| `media_id` | El de la subida, o uno que ya está en tu biblioteca. |
| `file_name`, `file_size` | Obligatorios para un archivo recién enviado. |
| `source_language` | Idioma hablado, como `pt`. Sin él, la detección es automática. Fíjalo en audios cortos: la detección confunde portugués con español. |
| `speaker_labels` | Identifica quién habla en cada frase. Cuesta más. |

### Espera a que esté lista

```bash
curl https://api.cut.pro/api/v1/transcriptions/7412950040021177 \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

Consulta cada 5 a 10 segundos mientras `status` sea `processing`. Termina en `ready`, `no_speech` (el audio no tiene voz) o `failed`. La respuesta trae `language`, `duration_seconds` y, con `speaker_labels`, `speaker_count`.

## Obtén el texto

En JSON, para indexar o dibujar tu propia interfaz:

```bash
curl https://api.cut.pro/api/v1/transcriptions/7412950040021177/transcript \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

```json title="200 OK"
{
  "language": "pt",
  "speaker_labels": true,
  "cues": [
    { "start": 0.48, "end": 3.12, "text": "Bem-vindo de volta ao programa.", "speaker": "A" },
    { "start": 3.40, "end": 5.95, "text": "Obrigado pelo convite.", "speaker": "B" }
  ]
}
```

Como archivo de subtítulos:

```bash
curl -o entrevista.srt "https://api.cut.pro/api/v1/transcriptions/7412950040021177/download?format=srt" \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

`format` acepta `srt` (predeterminado), `vtt` y `txt`. El cuerpo es el archivo, no JSON. En una transcripción con `speaker_labels`, los nombres de los hablantes entran en el archivo; `speakers=false` los quita.

Las dos rutas responden `409 TRANSCRIPTION_NOT_READY` mientras la transcripción se procesa.

## Costo

| Situación | Cobro |
|---|---|
| Transcripción nueva | Por minuto de audio medido (`duration_seconds`), debitado al empezar. |
| Con `speaker_labels` | Recargo por minuto. |
| El mismo archivo de nuevo | Gratis: responde `200 ready` al instante, con `credits_charged: 0`. |
| Audio sin voz | Gratis: `200 no_speech`. |

Para agregar hablantes a una transcripción que se hizo sin ellos, pídela de nuevo con el mismo `media_id` y `speaker_labels: true`. El audio se procesa otra vez y se cobra.

> `DELETE /transcriptions/{id}` saca la transcripción de las listas, pero el archivo queda en la biblioteca. Transcribir el mismo `media_id` después sale gratis.

## Errores

| Code | Cuándo |
|---|---|
| `INVALID_FILE_TYPE` | Extensión de archivo no aceptada. `extra.allowed_extensions` trae las aceptadas. |
| `FILE_TOO_LARGE` | Supera el tope efectivo, en `extra.max_size`. |
| `STORAGE_LIMIT_EXCEEDED` | El storage del plan está lleno. |
| `MEDIA_METADATA_REQUIRED` | Faltó `file_name` o `file_size` para un archivo recién enviado. |
| `MEDIA_TOO_LONG` | Duración por encima de lo permitido. `extra.duration` y `extra.max_duration` dicen cuánto. |
| `MEDIA_NOT_FOUND` | El `media_id` no existe en este workspace. |
| `MEDIA_UNREADABLE` | El archivo enviado no es un audio o video legible. |
| `INSUFFICIENT_CREDITS` | Saldo insuficiente. `extra.credits_needed` dice cuánto falta. |
