- 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>
3.4 KiB
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
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)
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):
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 dieurlaufwss://…zeigen.
Die Videoquelle
Der Publisher in html/js/webrtc.js holt sich den Stream in dieser Reihenfolge:
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.window.__aetherCapture()— optionaler Override, falls du eine bestimmte Quelle erzwingen willst (z. B. ein Aufnahmegerät).- 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".