# @abdulive/overlay-web Die Browser-Sources für OBS. Fünf Seiten, alle mit durchsichtigem Hintergrund, alle an demselben Ereignisstrom. Kein Build, kein Framework, keine Abhängigkeit: OBS lädt die Dateien direkt, und jede Zwischenstufe wäre ein Ding, das mitten im Stream kaputtgehen kann. Gemeinsam sind nur [`theme.css`](public/theme.css) (Farben, Schrift, Kontur) und [`client.js`](public/client.js) (Verbindung, Escaping, Emotes). ## Die Seiten | Adresse | Größe | Was sie zeigt | |---|---|---| | `/alerts` | 1920×1080 | Abos, Raids, Bits, Erstchatter. Eine nach der anderen, nie übereinander. | | `/chat` | 460×900 | Chatnachrichten mit Emotes, Abzeichen, Farben. | | `/status` | 1920×160 | Titel, Kategorie, Zuschauer, Laufzeit. | | `/effects` | 1920×1080 | Emote-Regen bei Chat-Spitzen, Konfetti bei Abos und Raids. | | `/starting` | 1920×1080 | Pausenbild als eigene Szene. Deckend, nicht durchsichtig. | | `/sounds` | 400×120 | Spielt die Sounds vom Pult. Unsichtbar, **mit Ton**. | Die fertigen Adressen mit Schlüssel stehen auf der Übersichtsseite (`/`). ## In OBS Je Seite eine Browser-Source anlegen, Adresse eintragen, Breite und Höhe setzen. Zwei Häkchen sind wichtig: - **"Quelle beim Unsichtbarwerden deaktivieren" aus.** Sonst verpasst das Overlay alles, was passiert, während eine andere Szene im Bild ist, und baut sich bei jedem Szenenwechsel neu auf. - **"Browser beim Szenenwechsel aktualisieren" aus.** Eine laufende Einblendung würde sonst mitten im Wechsel abgeschnitten. ## Einstellungen über die Adresse Es gibt keine Konfigurationsdatei. Was einstellbar ist, hängt hinten an der URL - so lässt es sich in OBS ändern, ohne den Dienst anzufassen. | Seite | Parameter | Vorgabe | |---|---|---| | alle | `probe=1` | dunkler Hintergrund zum Ansehen im Browser | | `/alerts` | `sekunden` | 7 - wie lange eine Einblendung steht | | `/alerts` | `erstchatter=0` | Erstchatter nicht einblenden | | `/chat` | `max` | 14 - so viele Zeilen gleichzeitig | | `/chat` | `sekunden` | 120 - danach verblasst eine Zeile (0 = nie) | | `/chat` | `befehle=1` | auch `!`-Befehle zeigen | | `/status` | `kanal` | abdulive_ | | `/effects` | `max` | 260 - Obergrenze für Teilchen | | `/starting` | `text`, `unter` | "Gleich geht es los", leer | ## Zum Ausprobieren Auf der Übersichtsseite (`/`) steht unter **Ausprobieren** für jede Einblendung, jede Chat-Variante und jeden Effekt ein Knopf. Er löst ein erfundenes Ereignis aus, das nur an die Browser-Sources geht - nichts davon landet in der Datenbank, auf Discord oder bei Twitch. Am besten die zu prüfende Seite über „ansehen" in einem zweiten Fenster offen haben. Dabei hilft `?probe=1`: das legt einen dunklen Grund unter die sonst durchsichtige Seite. Zwei Dinge sind gesperrt, solange ein Stream läuft: „Stream läuft" und die Vorführung. Beide setzen einen Zustand, der in der Statusleiste stehen bliebe, bis die nächste Twitch-Abfrage ihn geraderückt. „Stand zurücksetzen" ist absichtlich nie gesperrt - das ist der Weg aus einem erfundenen Zustand wieder heraus. Dieselben Ereignisse im Dauerbetrieb, auch ohne laufenden Dienst: ``` abdulive overlay --demo ``` Erfundener Chat, alle neun Sekunden eine Einblendung, ab und zu eine Chat-Spitze. Ohne das ließe sich eine Raid-Einblendung nur prüfen, indem man auf einen echten Raid wartet. ## Was fehlt - **Follows.** Kommen nicht über IRC, dafür braucht es EventSub. Bis dahin bleibt das Overlay bei Follows stumm; Abos, Raids und Bits kommen an. - **BTTV- und 7TV-Emotes.** Die hängen an einer zweiten API. Twitchs eigene Emotes werden angezeigt. - **Töne bei Einblendungen.** Es liegen keine Audiodateien im Repo, und ein Overlay, das ungefragt Krach macht, ist schlimmer als eines, das still ist. Sounds gibt es nur auf Knopfdruck, über das Pult. ## Das Pult (`/pult`) Keine Browser-Source, sondern eine App fürs Handy: wie ein Stream Deck, nur ohne Hardware. Mit Passwort, wie die Übersicht. Im Browser des Handys „Zum Startbildschirm hinzufügen“ (iPhone) bzw. „App installieren“ (Android), dann startet es ohne Adressleiste. `manifest.webmanifest` und `sw.js` machen das möglich; der Service Worker hält nur die Hülle vor und beantwortet nie einen Knopfdruck aus dem Speicher. | Reiter | Was | |---|---| | Sounds | Tasten fürs Soundboard. „+ Sound“ lädt MP3, WAV, OGG, WebM oder M4A vom Handy hoch (bis 8 MB). „Bearbeiten“: Name, Emoji, Farbe, Lautstärke, Reihenfolge, Löschen, am Handy anhören. „Stopp“ bricht alle Sounds ab. | | Szenen | OBS-Szenen umschalten, Clip aus dem Wiedergabepuffer speichern, Toneingänge stumm schalten. Braucht den Stream-PC (siehe unten). | | Stream | Liegestütze zählen, Vorlesen freigeben, „Sofort still“. | | Chat | Der Twitch-Chat, **nur lesend**: Abzeichen, Emotes, GIFs, Erstchatter hervorgehoben, Abos, Raids und Belohnungen als eigene Zeile, von Mods Gelöschtes durchgestrichen. | | Test | Dieselben Testknöpfe wie auf der Übersicht. | **Am Tablet** (ab 760 px Breite und 500 px Höhe) steht der Chat fest rechts und links der gewählte Reiter, der Chat-Reiter entfällt. Ohne gemerkten Reiter geht das Pult dort auf Szenen auf. Quer gehaltene Handys sind zu niedrig dafür und behalten die Reiter. Der Chat hängt am selben Ereignisstrom wie die Browser-Sources und schreibt nie. Er braucht kein Bot-Konto und keine weiteren Rechte bei Twitch. Nach dem Neuverbinden kommen die letzten 30 Nachrichten aus dem Schnappschuss, im Pult stehen höchstens 250. Wer hochscrollt, bleibt dort; „Neue Nachrichten“ springt zurück ans Ende. Die Sonne oben rechts hält den Bildschirm an (Wake Lock), solange das Pult offen ist. **Sounds** liegen auf dem Hub neben der Datenbank (`/sounds/`), nicht im Repo und nicht unter `/opt/abdulive` - sie überleben jedes Ausrollen. Der Dateityp wird an den ersten Bytes erkannt; was kein Ton ist, wird abgelehnt. Gespielt wird in OBS über die Browser-Source `/sounds`, „Audio über OBS steuern“ an. Ist sie nicht verbunden, sagt das Pult es in Gelb. Höchstens vier Sounds gleichzeitig (`?max=`), `?laut=` dämpft alle. **Szenen** gehen über den Stream-PC, weil der Hub OBS nicht erreicht. Der PC wählt sich mit eigenem Schlüssel beim Hub ein (`apps/ingest/src/fern.ts` und `apps/overlay-server/src/fern.ts`). In OBS muss nur obs-websocket an sein - dasselbe, was `!clip` braucht. Einzurichten ist nichts. Beim ersten Start würfelt `ingest` einen Schlüssel und meldet sich bei `fern.url` (Vorgabe `https://abdu.dimension47.de`, `FERN_URL=` schaltet ab). Im Pult unter Szenen steht dann „Stream-PC … möchte sich verbinden“ mit **Freigeben**. Ein Tipp, nach ein paar Sekunden ist er da. „Stream-PC trennen“ unten im Reiter würfelt den Schlüssel neu; danach muss er neu freigegeben werden. `abdulive fern:verbinden ` bleibt als Weg von Hand (Befehl auf der Übersicht). Jeder Knopf wartet auf die Antwort von OBS und sagt ehrlich, wenn es nicht ging. **Die Sound-Quelle legt der PC selbst an.** Nach dem Verbinden schickt der Hub die Adresse von `/sounds` mit Schlüssel, und `ingest` legt in OBS an: - die Szene `abdulive Ton` mit der Browser-Source `abdulive Sounds` darin („Audio über OBS steuern“ an, beim Unsichtbarwerden nicht abschalten); - in **jeder** Szene ein Verweis auf `abdulive Ton`. OBS gibt Ton nur aus Quellen der gerade gezeigten Szene aus; so gibt es die Quelle einmal, sie läuft beim Szenenwechsel durch und ist überall zu hören. Neue Szenen bekommen den Verweis sofort, ein neuer Overlay-Schlüssel wird in die Quelle nachgetragen. Die Ton-Szene taucht im Pult nicht als Szene auf, die Quelle aber unter Ton - damit lässt sich das Soundboard stumm schalten. Wer den Verweis aus einer Szene löscht, bekommt ihn beim nächsten Start zurück. Die App-Symbole zeichnet `node scripts/make-icons.ts`. ## Vorlesen (`/tts`) Eigene Browser-Source, 600×200, **mit Ton**. In OBS darf „Audio über OBS steuern" nicht ausgeschaltet sein, sonst hört der Stream nichts. Gesprochen wird im Hub mit Piper, nicht im Browser. Die eingebaute Sprachausgabe von OBS' Browser-Quelle sah keine deutsche Stimme und las amerikanisch; welche Stimmen es gibt, hängt am Rechner, der streamt. Piper läuft lokal im LXC, kostet nichts, und kein Zuschauertext verlässt das Haus. Die Seite holt sich die fertige WAV unter `/tts/audio/` und spielt sie über ein `