- Implemented the InternalWHIP component for managing WHIP server configurations. - Added functionality to load live WHIP state from Core and handle OBS URL generation. - Included polling for active streams and notifying parent components of state changes. - Created comprehensive tests for the InternalWHIP component covering various scenarios including fallback mechanisms and state changes. test: add integration tests for WHIP source component - Developed end-to-end tests for the InternalWHIP component to verify its behavior under different configurations. - Ensured that the component correctly handles the loading of WHIP state, displays appropriate messages, and emits the correct onChange events. test: add Settings WHIP configuration tests - Implemented tests for the WHIP settings tab to validate loading and saving of WHIP configurations. - Verified that the correct values are sent back to the Core when the user saves changes. - Ensured that the UI reflects the current state of the WHIP configuration after Core restarts or changes.
410 lines
14 KiB
Markdown
410 lines
14 KiB
Markdown
# Prompt de integración WHIP para Restreamer UI
|
|
|
|
> Este documento es el brief técnico completo para adaptar la UI de Restreamer de modo que exponga el servidor WHIP del Core de la misma manera que ya expone RTMP Server. Incluye dos casos de uso: **WHIP Server** (panel de estado + URL para OBS) y **WHIP Receive mode** (fuente de entrada en un proceso).
|
|
|
|
---
|
|
|
|
## Contexto del Core
|
|
|
|
El Core de datarhei expone las siguientes APIs relevantes:
|
|
|
|
### Config (`GET /api/v3/config`)
|
|
La sección `whip` dentro de `config` tiene esta forma:
|
|
```json
|
|
"whip": {
|
|
"enable": true,
|
|
"address": ":8555",
|
|
"token": ""
|
|
}
|
|
```
|
|
El campo `address` puede ser `:8555` (solo puerto) o `host:8555`.
|
|
|
|
### Canales activos (`GET /api/v3/whip`)
|
|
Devuelve la lista de streams que OBS/clientes están publicando en este momento:
|
|
```json
|
|
[
|
|
{
|
|
"name": "9VGyRCkCVCgj",
|
|
"published_at": "2026-03-14T02:51:36.799550551Z"
|
|
}
|
|
]
|
|
```
|
|
|
|
### URL de publicación WHIP (para OBS)
|
|
```
|
|
http://<host>:<whip_port>/whip/<stream_key>
|
|
```
|
|
Ejemplo: `http://192.168.1.15:8555/whip/mistream`
|
|
|
|
### URL de relay SDP (para FFmpeg / proceso interno)
|
|
```
|
|
http://localhost:<whip_port>/whip/<stream_key>/sdp
|
|
```
|
|
Esta es la URL que el Core inyecta automáticamente con `{whip}` como placeholder de input.
|
|
|
|
### Placeholder de proceso
|
|
En el config de un proceso de FFmpeg, el input address puede usar:
|
|
```
|
|
{whip:name=<stream_key>}
|
|
```
|
|
El Core lo expande a `http://localhost:<whip_port>/whip/<stream_key>/sdp` y agrega automáticamente `-protocol_whitelist file,crypto,http,rtp,udp,tcp` en las input options.
|
|
|
|
---
|
|
|
|
## Parte 1 — Panel "WHIP Server" (equivalente a "RTMP Server")
|
|
|
|
### Dónde ubicarlo
|
|
En la misma sección de configuración/status donde aparece **RTMP Server** y **SRT Server**. Añadir una tarjeta o sección llamada **WHIP Server**.
|
|
|
|
### Comportamiento esperado
|
|
|
|
#### 1.1 Indicador de estado
|
|
- Leer `config.whip.enable` de `GET /api/v3/config`
|
|
- Mostrar badge **Enabled** (verde) / **Disabled** (gris)
|
|
- Mostrar el puerto: extraer de `config.whip.address` (ej. `:8555` → `8555`)
|
|
|
|
#### 1.2 Campo "Stream URL para OBS"
|
|
Construir la URL de publicación a mostrar:
|
|
```
|
|
http://<host_público>:<whip_port>/whip/
|
|
```
|
|
- `host_público`: usar `config.host.name[0]` si `config.host.auto === true`, o el primer valor de `config.host.name`
|
|
- `whip_port`: extraer de `config.whip.address`
|
|
- Mostrar un campo de texto **read-only** con botón **Copiar**
|
|
- Indicar al usuario que al final de la URL debe agregar su **stream key** (ej. `mistream`)
|
|
|
|
Ejemplo visual:
|
|
```
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ WHIP Server URL │
|
|
│ http://192.168.1.15:8555/whip/ [Copiar] │
|
|
│ Ingresá tu stream key al final de la URL │
|
|
└─────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
#### 1.3 Campo "Stream Key"
|
|
- Input de texto editable donde el usuario escribe su stream key (ej. `mistream`, `obs-live`, etc.)
|
|
- Al escribirla, actualizar dinámicamente la URL completa a copiar:
|
|
`http://192.168.1.15:8555/whip/mistream`
|
|
- Botón **Copiar URL completa**
|
|
|
|
#### 1.4 Token de autenticación (opcional)
|
|
- Si `config.whip.token` no está vacío, mostrar un aviso: "Este servidor requiere un token. Agregá `?token=<token>` al final de la URL."
|
|
- Opcionalmente, ofrecer un checkbox "Incluir token en la URL" que lo appende automáticamente.
|
|
|
|
#### 1.5 Tabla de streams activos
|
|
- Hacer polling a `GET /api/v3/whip` cada 5 segundos
|
|
- Mostrar una tabla con columnas: **Stream Key** | **Publicando desde**
|
|
- Si la lista está vacía, mostrar "Sin streams activos"
|
|
|
|
```
|
|
┌──────────────────┬──────────────────────┐
|
|
│ Stream Key │ Publicando desde │
|
|
├──────────────────┼──────────────────────┤
|
|
│ 9VGyRCkCVCgj │ hace 3 minutos │
|
|
│ mistream │ hace 12 segundos │
|
|
└──────────────────┴──────────────────────┘
|
|
```
|
|
|
|
#### 1.6 Configuración WHIP (settings)
|
|
Sección colapsable o en la misma pantalla de configuración del Core:
|
|
- Toggle **Habilitar WHIP Server** → modifica `config.whip.enable` via `PATCH /api/v3/config`
|
|
- Campo **Puerto** → modifica `config.whip.address`
|
|
- Campo **Token** → modifica `config.whip.token`
|
|
|
|
---
|
|
|
|
## Parte 2 — Modo de recepción WHIP ("Receive mode")
|
|
|
|
### Dónde ubicarlo
|
|
En el wizard de creación/edición de un proceso (input source selector), junto a las opciones existentes como:
|
|
- Network Source (HLS, RTP, RTSP, etc.)
|
|
- RTMP Source
|
|
- SRT Source
|
|
- → **WHIP Source** ← (nueva opción)
|
|
|
|
### Comportamiento esperado
|
|
|
|
#### 2.1 Selector de protocolo
|
|
En la lista de protocolos de entrada agregar la opción:
|
|
```
|
|
WHIP (WebRTC HTTP Ingestion Protocol)
|
|
```
|
|
|
|
#### 2.2 Formulario de configuración de la fuente WHIP
|
|
Al seleccionar WHIP como fuente, mostrar:
|
|
|
|
**Stream Key** — campo de texto editable
|
|
(Se recomienda usar el ID del proceso por defecto, o dejar que el usuario lo cambie)
|
|
|
|
**URL de publicación para OBS** (campo read-only + botón Copiar):
|
|
```
|
|
http://<host_público>:<whip_port>/whip/<stream_key>
|
|
```
|
|
Actualiza en tiempo real mientras el usuario escribe el stream key.
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Protocolo de entrada: WHIP │
|
|
│ │
|
|
│ Stream Key: [mistream ] │
|
|
│ │
|
|
│ URL para OBS (copiar en OBS → Servicio WHIP): │
|
|
│ http://192.168.1.15:8555/whip/mistream [Copiar] │
|
|
│ │
|
|
│ Estado: ● Esperando publicador... │
|
|
│ ✓ Transmitiendo (si hay publisher activo) │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
#### 2.3 Indicador de estado en tiempo real
|
|
- Consultar `GET /api/v3/whip` cada 5 segundos
|
|
- Si `name === stream_key` aparece en la lista → mostrar "✓ Transmitiendo" (verde)
|
|
- Si no → "● Esperando publicador..." (gris/naranja)
|
|
|
|
#### 2.4 Address interno del proceso
|
|
Cuando el usuario guarda el proceso, el `input.address` debe configurarse como:
|
|
```
|
|
{whip:name=<stream_key>}
|
|
```
|
|
El Core lo expande a `http://localhost:<whip_port>/whip/<stream_key>/sdp` y agrega `-protocol_whitelist` automáticamente.
|
|
|
|
Si la UI no soporta el placeholder `{whip}`, puede usar directamente:
|
|
```
|
|
http://localhost:<whip_port>/whip/<stream_key>/sdp
|
|
```
|
|
Y agregar en `input.options` (ANTES de la URL, es decir, al principio del array):
|
|
```json
|
|
["-protocol_whitelist", "file,crypto,http,rtp,udp,tcp"]
|
|
```
|
|
|
|
**IMPORTANTE**: `-protocol_whitelist file,crypto,http,rtp,udp,tcp` debe estar presente para que FFmpeg pueda abrir los sub-protocolos RTP/UDP anidados dentro de la URL HTTP. Sin esta opción el probe devuelve `0x0 none`.
|
|
|
|
#### 2.5 Probe automático
|
|
Cuando el usuario hace clic en "Probe" o "Detectar streams":
|
|
- La UI puede invocar `GET /api/v3/process/<id>/probe` si el proceso ya existe
|
|
- O construir un payload de probe temporal equivalente
|
|
- El resultado correcto debe ser: `Video: h264, yuv420p, 1920x1080, 30fps` + `Audio: opus, 48000 Hz, stereo`
|
|
|
|
---
|
|
|
|
## Parte 3 — API endpoints completos de WHIP
|
|
|
|
### 3.1 `GET /api/v3/whip`
|
|
Lista todos los publishers activos en este momento.
|
|
|
|
**Response `200`:**
|
|
```json
|
|
[
|
|
{
|
|
"name": "mistream",
|
|
"published_at": "2026-03-14T02:51:36.799550551Z"
|
|
}
|
|
]
|
|
```
|
|
Usar con polling cada 5s para el panel de streams activos y el indicador de estado en Receive mode.
|
|
|
|
---
|
|
|
|
### 3.2 `GET /api/v3/whip/url` ⭐ nuevo
|
|
Devuelve la URL base del servidor WHIP y toda la info que la UI necesita para el panel "WHIP Server".
|
|
|
|
**Response `200`:**
|
|
```json
|
|
{
|
|
"base_publish_url": "http://192.168.1.15:8555/whip/",
|
|
"base_sdp_url": "http://localhost:8555/whip/",
|
|
"has_token": false,
|
|
"example_obs_url": "http://192.168.1.15:8555/whip/<stream-key>",
|
|
"input_address_template": "{whip:name=<stream-key>}"
|
|
}
|
|
```
|
|
|
|
- `base_publish_url` → mostrar en el panel WHIP Server; el usuario agrega su stream key al final
|
|
- `has_token` → si es `true`, mostrar aviso de token y el campo para incluirlo en la URL
|
|
- `example_obs_url` → texto de ayuda con placeholder visual
|
|
- `input_address_template` → usar como `input.address` al crear un proceso con WHIP como fuente
|
|
|
|
---
|
|
|
|
### 3.3 `GET /api/v3/whip/:name/url` ⭐ nuevo
|
|
Devuelve la URL completa de publicación para un stream key específico. **Este es el endpoint principal para generar la URL que el usuario copia en OBS.**
|
|
|
|
**Ejemplo:** `GET /api/v3/whip/mistream/url`
|
|
|
|
**Response `200`:**
|
|
```json
|
|
{
|
|
"publish_url": "http://192.168.1.15:8555/whip/mistream",
|
|
"sdp_url": "http://localhost:8555/whip/mistream/sdp",
|
|
"stream_key": "mistream"
|
|
}
|
|
```
|
|
|
|
- `publish_url` → campo read-only en la UI con botón **Copiar**. Es exactamente la URL que se pega en OBS → Configuración → Transmisión → Servidor.
|
|
- `sdp_url` → URL interna para FFmpeg (referencia, no se muestra al usuario en general).
|
|
- `stream_key` → confirmación del key procesado.
|
|
|
|
**Flujo de uso en la UI:**
|
|
1. Usuario escribe el stream key en el campo de texto
|
|
2. UI llama `GET /api/v3/whip/<stream_key>/url`
|
|
3. UI muestra `publish_url` en campo read-only con botón Copiar
|
|
4. Usuario copia y pega en OBS
|
|
|
|
---
|
|
|
|
### 3.4 `GET /api/v3/config`
|
|
Leer configuración del servidor WHIP para el panel de settings.
|
|
|
|
**Campos relevantes en la respuesta:**
|
|
```json
|
|
{
|
|
"config": {
|
|
"host": {
|
|
"name": ["192.168.1.15"],
|
|
"auto": true
|
|
},
|
|
"whip": {
|
|
"enable": true,
|
|
"address": ":8555",
|
|
"token": ""
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3.5 `PATCH /api/v3/config` (o `PUT`)
|
|
Modificar configuración WHIP desde el panel de settings.
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"whip": {
|
|
"enable": true,
|
|
"address": ":8555",
|
|
"token": "mi-token-secreto"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3.6 `POST /api/v3/process`
|
|
Crear un proceso con WHIP como fuente de entrada.
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"id": "mi-proceso",
|
|
"reference": "mi-proceso",
|
|
"input": [
|
|
{
|
|
"id": "in",
|
|
"address": "{whip:name=mistream}",
|
|
"options": []
|
|
}
|
|
],
|
|
"output": [
|
|
{
|
|
"id": "out",
|
|
"address": "rtmp://...",
|
|
"options": ["-c", "copy", "-f", "flv"]
|
|
}
|
|
],
|
|
"options": ["-loglevel", "level+info"]
|
|
}
|
|
```
|
|
|
|
> El Core expande `{whip:name=mistream}` → `http://localhost:8555/whip/mistream/sdp`
|
|
> e inyecta automáticamente `-protocol_whitelist file,crypto,http,rtp,udp,tcp`.
|
|
|
|
Si la UI no usa el placeholder `{whip}`, usar directamente:
|
|
```json
|
|
{
|
|
"address": "http://localhost:8555/whip/mistream/sdp",
|
|
"options": ["-protocol_whitelist", "file,crypto,http,rtp,udp,tcp"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3.7 `GET /api/v3/process/:id/probe`
|
|
Obtener información del stream (resolución, codec, fps) una vez el proceso existe.
|
|
|
|
**Response `200` (cuando OBS está transmitiendo):**
|
|
```json
|
|
{
|
|
"streams": [
|
|
{
|
|
"type": "video",
|
|
"codec": "h264",
|
|
"width": 1920,
|
|
"height": 1080,
|
|
"fps": 30,
|
|
"pix_fmt": "yuv420p"
|
|
},
|
|
{
|
|
"type": "audio",
|
|
"codec": "opus",
|
|
"sampling_hz": 48000,
|
|
"layout": "stereo",
|
|
"channels": 2
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Tabla resumen
|
|
|
|
| Endpoint | Método | Cuándo usarlo |
|
|
|---|---|---|
|
|
| `/api/v3/whip` | GET | Polling streams activos (cada 5s) |
|
|
| `/api/v3/whip/url` | GET | Panel WHIP Server — info base del servidor |
|
|
| `/api/v3/whip/:name/url` | GET | **Generar URL para OBS** dado un stream key |
|
|
| `/api/v3/config` | GET | Leer estado enable/disable, puerto, token |
|
|
| `/api/v3/config` | PATCH | Cambiar configuración desde settings |
|
|
| `/api/v3/process` | POST | Crear proceso con WHIP como input |
|
|
| `/api/v3/process/:id/probe` | GET | Detectar resolución/codec del stream |
|
|
|
|
---
|
|
|
|
## Parte 4 — Instrucciones para el usuario en la UI
|
|
|
|
### En el panel WHIP Server
|
|
```
|
|
Cómo transmitir desde OBS:
|
|
1. Abrí OBS → Configuración → Transmisión
|
|
2. Servicio: Personalizado
|
|
3. Servidor: http://<host>:<puerto>/whip/<tu-stream-key>
|
|
4. Clave de retransmisión: (dejar vacío)
|
|
5. Hacé clic en "Iniciar transmisión"
|
|
```
|
|
|
|
### En el Receive mode WHIP
|
|
```
|
|
Ingresá tu stream key, copiá la URL y configurala en OBS.
|
|
El proceso comenzará a recibir video cuando OBS empiece a transmitir.
|
|
```
|
|
|
|
---
|
|
|
|
## Notas técnicas para el desarrollador de la UI
|
|
|
|
1. **Compatibilidad de OBS**: OBS 30+ soporta WHIP nativo. En Configuración → Transmisión, seleccionar "Servicio: Personalizado" y pegar la URL completa.
|
|
|
|
2. **ICE / WebRTC**: El Core maneja ICE + DTLS-SRTP internamente. La UI no necesita gestionar nada de WebRTC, solo mostrar la URL HTTP.
|
|
|
|
3. **Protocolo WHIP**: El cliente (OBS) hace un `POST /whip/<key>` con SDP offer → el Core responde con SDP answer → ICE handshake → fluye RTP → el Core lo relay internamente a FFmpeg.
|
|
|
|
4. **`protocol_whitelist`**: Es obligatorio cuando FFmpeg lee la URL `/whip/<key>/sdp`. El Core lo inyecta automáticamente cuando detecta la URL en el config del proceso, pero si la UI construye el comando FFmpeg directamente debe asegurarse de incluirlo.
|
|
|
|
5. **Token de autenticación**: Si `config.whip.token` está configurado, la URL de publicación para OBS debe incluirlo como query param: `?token=<value>`. El OBS lo enviará en cada request al WHIP endpoint.
|
|
|
|
6. **Puertos**: Por defecto el WHIP server escucha en `:8555` (HTTP, sin TLS). El Core HTTP principal escucha en `:8080`. Son servidores independientes.
|
|
|
|
7. **Múltiples publishers**: El servidor WHIP soporta múltiples stream keys simultáneos. Cada stream key es independiente y genera su propio relay interno.
|