# Reproductor

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

Un reproductor profesional que incrustas con una línea, conectado a tu almacenamiento y a tu DRM. Es gratis: pagas la entrega y las licencias que la reproducción ya consume, no el reproductor.

## Qué es

Un **player** es una configuración con nombre — colores, controles, restricciones — guardada en tu cuenta. La incrustas en cualquier web con su id, junto al vídeo que quieras reproducir. Un player sirve para todo tu catálogo: el embed elige el contenido, el player pone el resto.

Por debajo es [Shaka Player](https://github.com/shaka-project/shaka-player), el reproductor de código abierto que mantiene Google: HLS y DASH adaptativos, mp4 progresivo, DRM. Nosotros añadimos la configuración persistente, la firma de URLs, la conexión con tu DRM y el embed de una línea.

> **Por qué es gratis:** Un reproductor no genera coste por existir. Lo que cuesta es lo que ya cobramos por sus propios servicios: los GB que sirve la CDN y las licencias DRM que emite tu cuenta. Cobrar además por el reproductor sería cobrar dos veces, y regalarlo hace más valioso todo lo demás.

¿Prefieres montar el reproductor tú mismo, con tu propio Shaka o Video.js? [La guía de integración manual](/docs/reproductores) sigue ahí — el player es opcional por diseño.

## Incrustarlo

Dos formas. La recomendada es el cargador: construye el iframe con los permisos correctos (`autoplay`, `encrypted-media`, pantalla completa), que escritos a mano se olvidan.

Con el cargador (recomendado):

```
<div data-airi-player="PLAYER_ID" data-file="FILE_ID"></div>
<script async src="https://airi.live/player.js"></script>
```

Iframe directo:

```
<iframe
  src="https://airi.live/embed/PLAYER_ID?file=FILE_ID"
  style="aspect-ratio:16/9;width:100%;border:0"
  allow="autoplay; encrypted-media; fullscreen; picture-in-picture"
  allowfullscreen></iframe>
```

`FILE_ID` es el id (o tu `customId`) de un fichero de tu almacenamiento: un mp4 suelto o un paquete HLS/DASH. Para una fuente externa usa `data-src="https://…"` en lugar de `data-file`. En una SPA que pinta el div después de cargar, llama a `AiriPlayer.scan()`.

| Atributo | Qué hace |
| --- | --- |
| `data-airi-player` | El id del player. Obligatorio. |
| `data-file` | Fichero de tu almacenamiento (id o customId). |
| `data-src` | URL https externa (mp4, m3u8 o mpd), sin firmar. |
| `data-aspect` | Proporción del contenedor (`16:9` por defecto). |
| `data-*` | Cualquier parámetro de la tabla siguiente, como atributo. |

## Parámetros por URL

Cada embed puede ajustar el player sin tocar su configuración guardada. La precedencia es **URL > configuración > defectos**, y solo alcanza a presentación y reproducción — la entrega (caducidades, países, velocidad) y los dominios permitidos no se pueden tocar desde una URL, por construcción.

| Parámetro | Qué hace |
| --- | --- |
| `autoplay=1` | Arranca solo, en silencio (política de los navegadores). |
| `muted=1` | Empieza sin sonido. |
| `loop=1` | Repite en bucle. |
| `t=90` | Empieza en el segundo 90. |
| `rate=1.5` | Velocidad inicial. |
| `maxh=720` | Techo de calidad en líneas. |
| `lang=en` | Idioma de los controles (`es`, `en`, `auto`). |
| `captions=es` | Subtítulos en ese idioma, visibles desde el inicio. |
| `audio=en` | Pista de audio preferida. |
| `poster=https://…` | Imagen de espera. |
| `accent=22ccaa` | Color de acento, hex sin #. |
| `bigplay=0` | Sin botón grande de play. |
| `controls=0` | Sin controles — para vídeos de fondo. |

## La configuración

El panel cubre lo habitual con vista previa en vivo. La superficie completa —orden exacto de los botones, velocidades del menú, colores de cada barra— vive en el objeto `config` del API, agrupada en cuatro bloques:

| Bloque | Qué contiene |
| --- | --- |
| `theme` | Colores de acento y de las barras, proporción, póster, logo con enlace, posición y opacidad. |
| `playback` | Autoplay, silencio, bucle, posición inicial, velocidad, techo de calidad, idiomas de audio y subtítulos. |
| `ui` | Qué botones aparecen y en qué orden, menú desbordante, velocidades, barra de progreso, botón grande, atajos de teclado, gestos móviles, idioma, título. |
| `delivery` | Vigencia de la URL firmada, países permitidos o bloqueados, tope de velocidad. Se aplican en el borde de la CDN. |

Todo es opcional: `{}` es un player completamente funcional con los defectos de Shaka. El esquema exacto, con cada campo documentado, está en la [referencia OpenAPI](https://kms.airi.live/docs) bajo `PlayerConfig`.

> **El panel no pisa lo que configures por API:** Guardar desde el panel conserva las claves que el formulario no gestiona — el orden de botones o las velocidades fijadas por API sobreviven. Pero `config` en un PATCH del API es un **reemplazo completo**: manda el objeto entero que quieras conservar.

## Por API

Los players se gestionan con los scopes `player:read` y `player:write`. El id que devuelve la creación es el que va en el embed.

Crear un player:

```
curl -X POST https://kms.airi.live/v1/players \
  -H "Authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{
    "name": "Mi player",
    "config": {
      "theme": { "accentColor": "#22ccaa" },
      "playback": { "muted": true }
    },
    "allowedOrigins": ["https://miweb.com"]
  }'
```

Gestión:

```
# Listar
curl "https://kms.airi.live/v1/players" -H "Authorization: Bearer $TOKEN"

# Actualizar (config = reemplazo completo; allowedOrigins: null la quita)
curl -X PATCH "https://kms.airi.live/v1/players/$ID" \
  -H "Authorization: Bearer $TOKEN" -H 'content-type: application/json' \
  -d '{ "config": { "ui": { "locale": "en" } } }'

# Borrar — todos los embeds con este id dejan de funcionar al momento
curl -X DELETE "https://kms.airi.live/v1/players/$ID" -H "Authorization: Bearer $TOKEN"
```

El embed llama a un endpoint público de resolución — `GET /v1/players/{id}/resolve` — que devuelve la configuración y, si se pide contenido, su URL firmada y los endpoints de licencia. Puedes llamarlo tú mismo para construir tu propio reproductor sobre nuestra resolución: no requiere token.

## Restringir a tus dominios

Un embed público funciona en cualquier web — es el modelo YouTube, y para la mayoría es lo correcto. Si quieres que tu player solo funcione en tus sitios, dale una lista de orígenes:

```
curl -X PATCH "https://kms.airi.live/v1/players/$ID" \
  -H "Authorization: Bearer $TOKEN" -H 'content-type: application/json' \
  -d '{ "allowedOrigins": ["https://miweb.com", "https://www.miweb.com"] }'
```

El muro de verdad no es una comprobación nuestra: el documento del embed responde con `Content-Security-Policy: frame-ancestors` y es **el navegador del espectador** el que se niega a pintar el iframe fuera de tu lista. La resolución además contesta 403 cuando el origen no cuadra, como fallo rápido.

> **Qué protege y qué no:** Protege contra el embed casual en webs ajenas — el caso real. No es DRM: quien pueda ver el vídeo siempre podrá grabar la pantalla, y las URLs firmadas caducan según `delivery.urlTtlSeconds`. Para contenido que necesita protección de verdad, cífralo al codificar: el player lo reproduce igual de fácil.

## DRM automático

Si un paquete salió cifrado de [tu codificación](/docs/codificacion), el embed lo sabe sin que configures nada: la resolución detecta la clave del trabajo y entrega los endpoints de licencia de tu propio DRM. La web que incrusta no ve claves ni URLs de licencia — solo el div y el script de siempre.

Cada reproducción con DRM emite licencias, y cada licencia se cobra a la tarifa de siempre ($0.009). Es el mismo coste con nuestro player o con el tuyo.

> **Safari y el contenido cifrado:** Los paquetes cifrados por nuestra codificación usan CENC (Widevine y PlayReady): reproducen en Chrome, Edge y Firefox. Safari solo reproduce FairPlay, que todavía no emitimos en la codificación — así que un embed cifrado en Safari muestra un error claro en vez de un spinner. El contenido sin cifrar reproduce en todos los navegadores, Safari incluido.

## Límites de esta versión

- **Sin Chromecast.** El botón de Cast llegará con un receptor propio; preferimos no enseñar un botón que falla.
- **FairPlay pendiente** — ver la nota de Safari, arriba.
- **`data-src` externo no lleva DRM**: una URL ajena no puede resolver licencias nuestras.
- **Los mp4 sueltos reproducen en progresivo**: sin escalera adaptativa ni menú de calidad. Codifícalos para tener ABR — es exactamente para lo que existe la codificación.
- **Sin analíticas de reproducción** todavía: los datos de entrega están en tu facturación diaria.
