- aether-medical: Stationen/Belegung, Intensivstation, Blutbank, Fuhrpark, Nachrichten/Aushänge, Berichte und Textbausteine (server + NUI) - aether-admin: vollständiges Server-Admin-Panel als echtes FiveM-Resource, an aether-core gekoppelt (Rechte über aether_users.admin_group), mit WebRTC-Live-Kameras (Bildschirmfreigabe) und separatem Media-Server (SFU) - Prototypen admin/ vervollständigt - SQL-Schema aether_admin.sql - Docker-Compose mit MariaDB und idempotenter Auto-Migration (schema_migrations) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
80 lines
3.4 KiB
Markdown
80 lines
3.4 KiB
Markdown
# aether-admin — Media-Server (WebRTC-SFU)
|
|
|
|
Router für die Live-Kameras des Admin-Panels. Er läuft **außerhalb** von
|
|
FiveM als eigener Node-Prozess und macht zweierlei:
|
|
|
|
- **Signaling + Medien (WebSocket, Standard `:8787`)** — Publisher senden
|
|
ihren Stream, Viewer empfangen ihn. Der Server leitet die RTP-Pakete
|
|
weiter (Selective Forwarding Unit).
|
|
- **Token-Ausgabe (HTTP, Standard `:8788`)** — nur der FiveM-Server ruft
|
|
das auf, abgesichert über ein gemeinsames Geheimnis.
|
|
|
|
Der FiveM-Server routet **kein Video** — er prüft nur Rechte, stellt Token
|
|
aus und weist Ziel-Clients an zu senden.
|
|
|
|
## Einrichtung
|
|
|
|
```bash
|
|
cd resources/[aether]/aether-admin/media-server
|
|
npm install
|
|
AETHER_MEDIA_SECRET="ein-langes-zufaelliges-geheimnis" node server.js
|
|
```
|
|
|
|
### Umgebungsvariablen
|
|
|
|
| Variable | Standard | Bedeutung |
|
|
|---|---|---|
|
|
| `AETHER_MEDIA_SECRET` | *(leer)* | Gemeinsames Geheimnis. **Muss** gesetzt sein und exakt der FiveM-Convar `aether_admin_media_secret` entsprechen. |
|
|
| `AETHER_MEDIA_WS_PORT` | `8787` | WebSocket-Port (von den NUIs erreichbar). |
|
|
| `AETHER_MEDIA_HTTP_PORT` | `8788` | HTTP-Port für die Token-Ausgabe (nur vom FiveM-Server erreichbar). |
|
|
|
|
### Passende FiveM-Convars (in `server.cfg`)
|
|
|
|
```cfg
|
|
set aether_admin_media_secret "ein-langes-zufaelliges-geheimnis"
|
|
set aether_admin_media_http "http://127.0.0.1:8788"
|
|
```
|
|
|
|
Und in `resources/[aether]/aether-admin/shared/config.lua` die öffentliche
|
|
WebSocket-Adresse (die die Spieler-Clients erreichen):
|
|
|
|
```lua
|
|
AdminConfig.Media.url = 'ws://DEINE-OEFFENTLICHE-IP:8787'
|
|
```
|
|
|
|
> Für den Produktivbetrieb hinter TLS (`wss://`) einen Reverse-Proxy
|
|
> (nginx/Caddy) vor den WS-Port setzen und die `url` auf `wss://…` zeigen.
|
|
|
|
## Die Videoquelle
|
|
|
|
Der Publisher in `html/js/webrtc.js` holt sich den Stream in dieser Reihenfolge:
|
|
|
|
1. **`getDisplayMedia` — der Standardweg ohne externes Werkzeug.** Die NUI
|
|
gibt das Spielfenster über die Bildschirmfreigabe-API frei; das ist echtes,
|
|
flüssiges Video und braucht **kein OBS und keine Virtual-Cam**.
|
|
2. `window.__aetherCapture()` — optionaler Override, falls du eine bestimmte
|
|
Quelle erzwingen willst (z. B. ein Aufnahmegerät).
|
|
3. Ein rot beschrifteter **Platzhalter** — erscheint nur, wenn die
|
|
Bildschirmfreigabe abgelehnt/blockiert wurde, damit die Strecke trotzdem
|
|
nachweislich live ist.
|
|
|
|
**Die entscheidende Abhängigkeit:** Ob `getDisplayMedia` klappt, hängt davon
|
|
ab, ob das **FiveM-CEF des Ziel-Clients** Bildschirmaufnahme aus einer
|
|
Hintergrund-NUI erlaubt (Nutzergesten-/Berechtigungskontext). Erlaubt es das,
|
|
siehst du das Live-Bild flüssig im Panel. Verweigert es das, kann kein
|
|
Resource das erzwingen — dann bleibt nur eine externe Quelle über
|
|
`__aetherCapture` oder die native Spectate-Funktion (Knopf „Beobachten").
|
|
|
|
Das Panel meldet pro Ziel-Client zurück, was gegriffen hat: eine Toast-Meldung
|
|
„Bild live" oder „Bildschirmfreigabe blockiert (Fehlergrund)".
|
|
|
|
## Betrieb & Hinweise
|
|
|
|
- Als Dienst betreiben (pm2/systemd), Neustart bei Absturz.
|
|
- **Live-Test nötig:** Ein WebRTC-SFU lässt sich nur im laufenden Betrieb
|
|
sinnvoll prüfen. Je nach `werift`-Version können Details der Signaling-
|
|
oder RTP-API minimal abweichen — der Code ist die klar strukturierte
|
|
Referenz und an einer Stelle (`publisherTrack`) leicht anzupassen.
|
|
- Ohne gesetztes Geheimnis lehnt der Server jede Token-Ausgabe ab; das
|
|
Panel zeigt dann den Hinweis „Media-Server nicht erreichbar".
|