Proyecto kiradesktop - escritorio virtual CPU/GPU para captura DRM
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
# KiraDesktop
|
||||
|
||||
Sistema de escritorios virtuales remotos (X11 + XFCE) pensado para **captura de
|
||||
streams con protección DRM (Widevine L3) reproducidos en Firefox**. Cada
|
||||
instancia levanta un escritorio Linux headless, expone acceso VNC para
|
||||
control/depuración y ofrece una API REST que produce un stream de vídeo+audio
|
||||
en formato MPEG-TS (vía `ffmpeg`) listo para consumir con cualquier
|
||||
reproductor/pipeline aguas abajo.
|
||||
|
||||
La idea general: como el contenido DRM no se puede volcar "en crudo" (el
|
||||
decodificador protege los frames), se renderiza en una sesión X11 real dentro
|
||||
de Firefox y se captura la salida de pantalla (X11 grab) + audio (PulseAudio
|
||||
null-sink), re-codificando con `ffmpeg` a H.264/AAC en MPEG-TS. El resultado es
|
||||
funcionalmente equivalente a "grabar la pantalla" del escritorio remoto.
|
||||
|
||||
## Arquitectura: variante CPU vs variante GPU
|
||||
|
||||
### Variante CPU (`cpu/`)
|
||||
|
||||
- Contenedores LXC (Proxmox `pct`), clonados: `kiradesktop-cpu-1` ...
|
||||
`kiradesktop-cpu-12`. Son **12 instancias idénticas** en el cluster, cada
|
||||
una con **1 escritorio** por contenedor.
|
||||
- Servidor VNC: `Xtigervnc` (framebuffer virtual, no requiere GPU).
|
||||
- Captura: `ffmpeg` con `-f x11grab` + encoder software `libx264` (preset
|
||||
`superfast`, escalado a 1280x720 para aliviar la carga de CPU aunque el VNC
|
||||
se sirve en 1080p).
|
||||
- Cada contenedor corre un único proceso (`kiradesktop-cpu.py`) que gestiona
|
||||
ese único escritorio (`/desktop/0/...`).
|
||||
- Incluye `kiradesktop.py`, una versión anterior/backup del mismo script. Ver
|
||||
sección "Diferencias" más abajo.
|
||||
|
||||
### Variante GPU (`gpu/`)
|
||||
|
||||
- Una VM KVM (`kirastream-gpu1`, Proxmox VM id 211) con GPU NVIDIA pasada por
|
||||
passthrough/vGPU.
|
||||
- Servidor VNC: `x11vnc` sobre sesiones `Xorg` reales con el driver NVIDIA
|
||||
(permite aceleración GLX/VDPAU y decodificación por hardware NVDEC/VA-API
|
||||
dentro de Firefox: `LIBVA_DRIVER_NAME=nvidia`, `MOZ_X11_EGL=1`).
|
||||
- Captura: `ffmpeg` con `-f x11grab` + encoder por hardware `h264_nvenc`.
|
||||
- Un único proceso (`kiradesktop-gpu.py`) gestiona **hasta 6 escritorios en
|
||||
paralelo** (`/desktop/{0..5}/...`), cada uno con su propio display
|
||||
(`:1`-`:6`), puerto VNC (`5901`-`5906`) y PulseAudio aislado.
|
||||
|
||||
## API REST (puerto 8900 en ambas variantes)
|
||||
|
||||
| Método | Ruta | Descripción |
|
||||
|--------|-----------------------------------------|---------------------------------------|
|
||||
| GET | `/health` | Estado de escritorio(s) |
|
||||
| POST | `/desktop/{id}/start` | Arranca el escritorio `id` |
|
||||
| POST | `/desktop/{id}/stop` | Detiene el escritorio `id` |
|
||||
| GET | `/desktop/{id}/stream` | Stream MPEG-TS (multi-cliente) |
|
||||
| GET | `/sync/firefox/export[/{slot}]` | Exporta el perfil de Firefox (.tar.gz)|
|
||||
| POST | `/sync/firefox/import` | Importa un perfil de Firefox |
|
||||
|
||||
En la variante CPU `{id}` es siempre `0` (un solo escritorio por contenedor).
|
||||
En la variante GPU `{id}` va de `0` a `5` (hasta 6 escritorios por VM).
|
||||
|
||||
## Puertos
|
||||
|
||||
- **8900/tcp** — API REST (FastAPI + uvicorn, `0.0.0.0:8900`).
|
||||
- **5901/tcp** (y consecutivos `5902`-`5906` en GPU) — VNC directo al
|
||||
framebuffer X11 de cada escritorio.
|
||||
|
||||
## Despliegue (systemd)
|
||||
|
||||
Cada instancia corre como servicio systemd (`kiradesktop.service` en CPU,
|
||||
`kiradesktop-gpu.service` en GPU) con `Restart=always` y toda la configuración
|
||||
por variables de entorno — así el mismo `.py` sirve para las 12 instancias CPU
|
||||
clonadas y para la VM GPU, cambiando solo el entorno:
|
||||
|
||||
- `MY_IP` — IP pública/interna que se anuncia en las respuestas de la API
|
||||
(`vnc_addr`, `stream_url`). **Debe fijarse por instancia** al clonar el
|
||||
contenedor/VM (es lo único que realmente cambia entre clones CPU).
|
||||
- `RESOLUTION`, `FRAMERATE`, `VIDEO_BITRATE`, `AUDIO_BITRATE` — parámetros de
|
||||
codificación.
|
||||
- `VNC_PORT` / `BASE_VNC_PORT` — puerto(s) VNC.
|
||||
- `WM_CMD` — gestor de ventanas a lanzar (`startxfce4` por defecto).
|
||||
- Variante GPU además: `NUM_DESKTOPS` (6), `BASE_DISPLAY`, `NVENC_PRESET`,
|
||||
`XORG_CONFIG` (ruta al `xorg.conf` con el driver NVIDIA).
|
||||
|
||||
Instalación típica en cada nodo:
|
||||
|
||||
```bash
|
||||
cp kiradesktop-cpu.py /opt/kiradesktop-cpu.py # o kiradesktop-gpu.py
|
||||
cp kiradesktop.service /etc/systemd/system/ # o kiradesktop-gpu.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now kiradesktop.service # o kiradesktop-gpu.service
|
||||
```
|
||||
|
||||
## Diferencias entre `kiradesktop.py` y `kiradesktop-cpu.py`
|
||||
|
||||
`cpu/kiradesktop.py` es una **versión previa/backup** del script CPU actual
|
||||
(`cpu/kiradesktop-cpu.py`), tal como se encontró en `/opt` del contenedor. Se
|
||||
incluye igual por trazabilidad histórica, pero **el que está desplegado y en
|
||||
uso (referenciado por el `.service`) es `kiradesktop-cpu.py`**.
|
||||
|
||||
La diferencia real entre ambos archivos es mínima:
|
||||
|
||||
- Se eliminó un comentario explicativo sobre el escalado a 720p.
|
||||
- Se cambió el preset del encoder `libx264` de `ultrafast` a `superfast`
|
||||
(mejor relación calidad/CPU a cambio de un poco más de carga).
|
||||
|
||||
El resto del código (gestión de PulseAudio, Xtigervnc, ffmpeg, API FastAPI,
|
||||
export/import de perfil de Firefox) es idéntico.
|
||||
|
||||
## Nota de seguridad (importante para un despliegue real)
|
||||
|
||||
Los servidores VNC de ambas variantes se levantan **sin contraseña**
|
||||
(`Xtigervnc -SecurityTypes None` en CPU, `x11vnc -nopw` en GPU) y la API REST
|
||||
no implementa autenticación. Esto asume que el servicio corre en una red
|
||||
interna/confiable (o detrás de un firewall/VPN/reverse-proxy que añada auth).
|
||||
**No exponer el puerto 8900 ni los puertos VNC directamente a Internet** sin
|
||||
añadir una capa de autenticación (por ejemplo, un proxy con Basic Auth o un
|
||||
túnel VPN) delante de ambos servicios.
|
||||
|
||||
No se encontraron contraseñas, tokens ni claves de API hardcodeadas en el
|
||||
código (se auditó con `grep -iE "password|secret|token|key"` antes de subir
|
||||
el repo).
|
||||
|
||||
## Requisitos
|
||||
|
||||
- Python 3 con `fastapi`, `uvicorn`.
|
||||
- `ffmpeg` (con soporte `libx264` en CPU, o `h264_nvenc`/driver NVIDIA en GPU).
|
||||
- `pulseaudio`, `dbus-launch`, XFCE (`startxfce4`) o el WM que se configure.
|
||||
- CPU: `Xtigervnc`. GPU: `Xorg` + driver propietario NVIDIA + `x11vnc`.
|
||||
Reference in New Issue
Block a user