# Codificación

Source: https://airi.live/docs/codificacion
Language: es. The other: https://airi.live/docs/codificacion.md?lang=en
Index: https://airi.live/llms.txt — every page in one file: https://airi.live/llms-full.txt

Convierte un máster en las calidades que un reproductor necesita, empaquetado para streaming adaptativo y cifrado si quieres. Las salidas aparecen en tu almacenamiento, listas para servir.

## Cómo funciona

Envías un trabajo diciendo qué fichero codificar y a qué calidades. Contestamos **202** con un trabajo en cola: la codificación tarda minutos, así que no se espera a que termine. Cuando acaba, cada salida aparece como un fichero tuyo en el almacenamiento y ya se puede servir con una URL firmada.

El origen puede ser un fichero que ya tengas en tu almacenamiento (`sourceFileId`) o una URL pública (`sourceUrl`). Si es tuyo, se lo entregamos al codificador con un permiso temporal — **tu fichero no se hace público en ningún momento**, y ese tirón no te cuenta como transferencia.

> **El frame rate es un techo:** Por defecto limitamos la salida a 30 fps. Un máster que ya esté por debajo **no se toca** — una película a 24 fps sale a 24 — y solo se baja lo que venga más rápido. Subir el techo a 60 con `fps: 60` duplica el precio del vídeo y su peso; y tampoco inventa fotogramas: de un máster a 30 salen 30, y se cobran 30.

> **No se escala hacia arriba:** Pedir 1080p de un máster de 720p produce 720p, no un 1080p borroso. Y se te cobra el 720p que sale, no el 1080p que pediste: el presupuesto es un techo, y la factura se liquida contra lo que realmente se produjo.

## Enviar un trabajo

Dos calidades, empaquetado HLS y DASH, cifrado con tus claves:

```
curl -X POST https://kms.airi.live/v1/encoding/jobs \
  -H "Authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{
    "sourceFileId": "a1b2c3d4-…",
    "heights": [1080, 720],
    "durationSeconds": 600,
    "package": "hls+dash",
    "drm": true
  }'
```

| Campo | Qué hace |
| --- | --- |
| `heights` | Las calidades: 240, 360, 480, 720, 1080, 1440 o 2160 |
| `codec` | `h264` (por defecto) o `hevc`. HEVC ocupa ~40% menos y cuesta el doble |
| `fps` | Un **techo**, no un objetivo: 30 por defecto, 60 si lo subes. Una película a 24 fps se queda en 24 |
| `package` | `none`, `hls`, `dash` o `hls+dash`. Un paquete es lo que permite cambiar de calidad sobre la marcha |
| `mp4` | Si además quieres un MP4 suelto por calidad. Por defecto sí |
| `drm` | Cifrar los paquetes con una clave de tu propio KMS |
| `durationSeconds` | Cuánto dura el máster. Solo dimensiona la reserva — ver abajo |
| `customId` | Tu identificador. Sirve de clave de idempotencia |

El `customId` hace que reenviar el mismo trabajo sea seguro: una petición idéntica que se cortó por red devuelve **el trabajo que ya empezó**, y se paga una vez. Reusar el mismo identificador con otra escalera choca, en vez de ignorar en silencio lo que pediste.

## Qué cuesta

Se cobra **por minuto de salida, por calidad, y una vez por cada formato entregable**. Diez minutos a 1080p y 720p son veinte minutos de salida, no diez. Y si además pides MP4, HLS y DASH, son tres pasadas de esa escalera.

| Calidad | H.264 | HEVC |
| --- | --- | --- |
| Hasta 480p | $0.0065 /min | $0.013 /min |
| 720p y 1080p | $0.013 /min | $0.026 /min |
| 1440p | $0.0325 /min | $0.065 /min |
| 4K | $0.0585 /min | $0.117 /min |
| Audio (por salida) | $0.0013 /min | $0.0013 /min |

Antes de gastar nada puedes preguntar el precio exacto, con el mismo código que luego cobra:

```
curl "https://kms.airi.live/v1/encoding/quote?heights=1080,720&durationSeconds=600" \
  -H "Authorization: Bearer $TOKEN"
```

> **Reserva al enviar, liquidación al terminar:** El precio se reserva de tu saldo **antes** de llamar al codificador, porque una codificación no se puede deshacer. Al terminar se liquida contra la duración que midió el codificador y las calidades que realmente salieron: si sobró, se te devuelve. Por eso `durationSeconds` solo dimensiona la reserva — declarar de menos no abarata la factura.

Se cobra por fracción de minuto, no por minuto empezado: un clip de diez segundos paga un sexto de minuto. Un trabajo cifrado cuesta además **una clave**, a la tarifa habitual de DRM. Y un trabajo que falla **no te cuesta nada**: se borra lo que hubiera salido y se te devuelve la reserva entera.

## Paquetes y DRM

Un paquete HLS o DASH es una carpeta con un manifiesto y sus segmentos. En tu almacenamiento aparece como **un solo fichero** que pesa la carpeta entera, y su URL firmada cubre toda la carpeta automáticamente — es lo que hace que los segmentos resuelvan.

Con `drm: true` pedimos una clave a tu propio KMS y se la pasamos al codificador, así que el paquete sale ya cifrado y **con la URL de licencia dentro del manifiesto**. Señaliza Widevine y PlayReady a la vez, en una sola pasada.

> **Un trabajo cifrado entrega dos paquetes:** Los tres DRM no caben en un solo empaquetado, así que un trabajo con `drm: true` produce **dos, bajo la misma clave**: un **DASH** cifrado con CENC para **Widevine y PlayReady** (Chrome, Edge, Firefox, Android) y un **HLS** cifrado con SAMPLE-AES para **FairPlay** (Safari, iOS, tvOS). No es un rodeo: Apple exige SAMPLE-AES y los otros dos exigen CENC. Pidas `hls`, `dash` o los dos, recibes ambos — de nada sirve entregarte medio catálogo de plataformas.

> **Lo comprobamos, no lo suponemos:** Antes de entregarte un paquete cifrado leemos su segmento de inicialización y verificamos que lleva la caja `tenc`, que es lo que dice que los datos están realmente cifrados. Si no la lleva, el trabajo se marca fallido, se borra lo producido y se te devuelve el dinero. Preferimos un fallo visible a un paquete que parece protegido y no lo está.

> **Los MP4 sueltos no se cifran:** Solo se cifran los paquetes: una descarga progresiva no es un formato de entrega protegida, y fingir lo contrario sería peor que no ofrecerlo. Si pides `drm: true` sin paquete, el trabajo se rechaza en vez de salir en claro sin avisar.

## Seguir el trabajo

```
curl "https://kms.airi.live/v1/encoding/jobs/$ID" -H "Authorization: Bearer $TOKEN"
```

- **queued:** Aceptado, esperando en el proveedor
- **running:** Codificando
- **finalising:** Terminó; estamos midiendo y creando tus ficheros
- **completed:** Listo. `outputFileIds` son tus ficheros
- **failed:** Falló. No se te ha cobrado nada
- **cancelled:** Lo cancelaste

> **Cancelar no detiene la codificación:** El proveedor no ofrece forma de abortar una tarea en marcha, así que el trabajo termina igual y lo pagamos nosotros. Cancelar significa que **a ti** dejamos de cobrártelo, y se borra lo que hubiera salido.

## Permisos

- **`encoding:write`:** Enviar y cancelar trabajos.
- **`encoding:read`:** Consultar trabajos y pedir presupuestos.
- **`storage:read`:** Necesario si el origen es un fichero tuyo.
