Files
decap-stream/README.md
T
Kralot 1f8385e450 Migrate to Chromium, unified VNC, thumbnails, autologin CDP detection
---

- Migrado base Docker de ubuntu:22.04 + Google Chrome para debian:bookworm-slim + Chromium
- Dockerfile refatorado com multi-stage build (node:22-alpine builder + debian runtime) e single RUN layer para imagem menor
- VNC unificado: removido novnc por stream, substituído por websockify global na porta 6080 com token-based routing
- Implementado sistema de thumbnails por stream via ffmpeg (captura do HLS) com endpoint GET/POST e atualização no card
- Autologin reescrito com detecção via Chrome DevTools Protocol: pula credenciais se já autenticado
- Adicionado padrão desiredState (running/stopped) persistido no JSON, restaurado via restore-streams.sh ao reiniciar container
- UI traduzida para inglês, formulário reorganizado com tooltips, seção avançada colapsável e GOP automático
- Player simplificado: modos HLS e HTML unificados, removido modo m3u8 separado
- Adicionado campo threads no ffmpeg; suporte a seccomp:unconfined no docker-compose

---
2026-04-24 23:08:42 -03:00

150 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DecapStream
Turn any web page into an RTMP/HLS stream. Chromium renders the page, ffmpeg captures it, MediaMTX publishes it. Built for NOC environments and digital signage.
## How it works
Each stream runs its own isolated stack inside the container:
```
Xvfb (virtual display)
└── Chromium (opens the URL)
└── ffmpeg (x11grab → libx264 → RTMP → MediaMTX → HLS)
└── x11vnc (live VNC access via noVNC)
```
All processes are managed by Supervisord. The web UI is a Next.js app that controls everything via a REST API.
## Features
- **Stream any URL** — if it loads in a browser, it streams
- **Dashboard with live thumbnails** — captured from the HLS output, refreshable on demand
- **VNC access** — inspect any stream's virtual display from the browser via unified noVNC (single port, token routing)
- **Autologin with CDP detection** — configure credentials per stream; on restart, queries Chrome DevTools Protocol to skip login if the session is still alive
- **Persistent desired state** — streams remember if they were running or stopped and restore automatically on container restart
- **Fully configurable encoding** — resolution, scale, FPS, bitrate, preset, tune, GOP, threads, all per stream
- **Built-in HLS player** — watch any stream in the browser; also serves a standalone embeddable HTML page per stream
## Quick Start
```yaml
# docker-compose.yml
services:
decap-stream:
image: ghcr.io/riguettodev/decap-stream:latest
container_name: decap-stream
restart: unless-stopped
shm_size: "2gb"
security_opt:
- seccomp:unconfined # required for Chromium syscalls
environment:
TZ: America/Sao_Paulo
ports:
- "3000:3000" # Web UI
- "1935:1935" # RTMP input
- "8888:8888" # HLS output
- "6080:6080" # noVNC
volumes:
- decap-stream:/app/data
volumes:
decap-stream:
```
```bash
docker compose up -d
```
Open **http://localhost:3000** and add your first stream.
> `seccomp:unconfined` is required because Chromium uses syscalls blocked by Docker's default seccomp profile.
> `shm_size: 2gb` prevents Chromium from crashing on `/dev/shm` exhaustion under load.
## Ports
| Port | Service |
|------|---------|
| `3000` | Web UI (Next.js) |
| `1935` | RTMP ingest (MediaMTX) |
| `8888` | HLS output (MediaMTX) |
| `6080` | noVNC unified (token-based routing to all streams) |
## RTMP & HLS URLs
Each stream gets a slug ID you define (e.g. `grafana-prod`):
| Protocol | URL |
|----------|-----|
| RTMP ingest | `rtmp://<host>:1935/live/<id>` |
| HLS manifest | `http://<host>:8888/live/<id>/index.m3u8` |
| VNC | `http://<host>:6080/vnc.html?autoconnect=true&path=websockify%3Ftoken%3D<id>` |
## Stream Configuration
| Field | Default | Description |
|-------|---------|-------------|
| `id` | | Unique slug (lowercase, numbers, hyphens) |
| `name` | | Display name |
| `url` | | URL to open in Chromium |
| `user` / `pass` | | Credentials for autologin (optional) |
| `delay` | `15s` | Seconds before ffmpeg starts (allows page to load) |
| `resolution` | `1920x1080` | Virtual display and capture size |
| `scale` | `1280x720` | Output video resolution |
| `fps` | `30` | Capture framerate |
| `bitrate` | `1500k` | Video bitrate |
| `bufsize` | `3000k` | Encoder buffer size |
| `preset` | `ultrafast` | x264 preset |
| `tune` | `stillimage` | x264 tune (`stillimage` for dashboards, `zerolatency` for dynamic content) |
| `gop` | `60` | Keyframe interval (auto-calculated as 2× FPS in the UI) |
| `threads` | `0` | ffmpeg encoding threads (`0` = auto-detect) |
## Architecture
```
┌──────────────────────────────────────────────────────────────┐
│ Container │
│ │
│ Next.js :3000 ──API──► Supervisord │
│ ├── novnc :6080 (global) │
│ └── per stream: │
│ ├── xvfb (display) │
│ ├── chromium (browser) │
│ ├── autologin (CDP) │
│ ├── x11vnc (VNC) │
│ └── ffmpeg (encode) │
│ │ │
│ MediaMTX :1935/:8888 ◄────RTMP────────┘ │
└──────────────────────────────────────────────────────────────┘
```
- `streams.json` flat file + one directory per stream under `/app/data/streams/{id}/`
- Each stream generates a `stream.conf` from a template; Supervisord picks it up via `[include]`
- Display number `:n` is auto-allocated; VNC port = `5900+n`, debug port = `9221+n`
## Development
```bash
npm install
npm run dev # dev server — supervisorctl calls are mocked automatically
npm run build # build Next.js standalone
npm run lint
./build.sh # interactive Docker build
```
In dev mode (`NODE_ENV !== "production"`), all `supervisorctl` and `captureThumb` calls are replaced with console logs.
## Stack
- [Next.js 15](https://nextjs.org/) + TypeScript + Tailwind CSS v4
- [Supervisord](http://supervisord.org/)
- [MediaMTX](https://github.com/bluenviron/mediamtx)
- [HLS.js](https://github.com/video-dev/hls.js/)
- [noVNC](https://novnc.com/)
- Chromium, ffmpeg
## License
MIT