Initial commit
This commit is contained in:
commit
6aa9bf85f3
10 changed files with 660 additions and 0 deletions
60
README.md
Normal file
60
README.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# zoitestream
|
||||
|
||||
Landing page + lightweight API for `stream.dumpnet.chat`, backed by
|
||||
[MediaMTX](https://github.com/bluenviron/mediamtx).
|
||||
|
||||
This is intentionally tiny: a single Flask process with a SQLite database
|
||||
(on a persistent volume, not container-local disk) tracking the currently
|
||||
active stream and stream history. MediaMTX calls this service's `/hooks/*`
|
||||
endpoints on stream start/stop (via its `runOnReady`/`runOnNotReady` path
|
||||
hooks), and the landing page polls `/api/active` and `/api/history` to
|
||||
render status. An IRC bot can call `/api/creds` to fetch the current
|
||||
publish URL to hand out to whoever wants to stream.
|
||||
|
||||
State persists across pod restarts/redeploys (SQLite file lives on the
|
||||
shared `appdata` hostPath PV, mounted at `STATE_DB_PATH`).
|
||||
|
||||
## Design notes
|
||||
|
||||
- One shared publish stream/password for everyone (a deliberate feature,
|
||||
not a limitation) — credentials are retrievable via `/api/creds` (meant
|
||||
for the IRC bot to call), never shown on the public landing page. The
|
||||
IRC channel is a high-trust environment, so this endpoint is only
|
||||
lightly protected (shared token), not treated as a hard secret boundary.
|
||||
- `/hooks/ready` and `/hooks/not-ready` are protected by a separate shared
|
||||
token (`HOOK_TOKEN`) so MediaMTX is the only thing that can flip stream
|
||||
status — rotatable independently of the creds token.
|
||||
- Publish password itself lives in MediaMTX's own internal auth config
|
||||
(`authInternalUsers`), not validated by zoitestream — zoitestream just
|
||||
knows the current value (via `PUBLISH_PASSWORD` env var, sourced from
|
||||
the same secret) so it can hand it back out through `/api/creds`.
|
||||
- No scheduling API yet — planned as a future addition, likely driven by
|
||||
an IRC bot, and will live in the same SQLite database.
|
||||
|
||||
## Endpoints
|
||||
|
||||
- `GET /` — landing page
|
||||
- `GET /api/active` — JSON list of currently active streams
|
||||
- `GET /api/history` — JSON list of recent streams (capped, most-recent-first)
|
||||
- `GET /api/creds` — publish URL/user/password (token-protected via `CREDS_TOKEN`)
|
||||
- `GET /health` — health check
|
||||
- `POST /hooks/ready` — called by MediaMTX `runOnReady` (form/query: `path`, `source_type`)
|
||||
- `POST /hooks/not-ready` — called by MediaMTX `runOnNotReady` (form/query: `path`)
|
||||
|
||||
## Env vars
|
||||
|
||||
- `HOOK_TOKEN` — shared secret required (as `?token=` or `X-Hook-Token` header) on `/hooks/*`
|
||||
- `CREDS_TOKEN` — shared secret required (as `?token=` or `X-Creds-Token` header) on `/api/creds`
|
||||
- `PUBLISH_USER` — publish username to report via `/api/creds` (default `streamer`)
|
||||
- `PUBLISH_PASSWORD` — publish password to report via `/api/creds` — must match MediaMTX's own config
|
||||
- `DOMAIN` — display domain shown on the landing page and in `/api/creds` (default `stream.dumpnet.chat`)
|
||||
- `RTMP_PORT` — RTMP port used in the URL built by `/api/creds` (default `1935`)
|
||||
- `STATE_DB_PATH` — path to the SQLite file (default `/data/zoitestream.db`)
|
||||
- `HISTORY_LIMIT` — number of history entries to retain (default `50`)
|
||||
|
||||
## Local dev
|
||||
|
||||
```
|
||||
uv sync
|
||||
STATE_DB_PATH=./dev.db uv run flask --app wsgi:app run --debug
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue