Overlay: fuenf Browser-Sources fuer OBS
Einblendungen, Chat, Statusleiste, Effekte, Pausenbild. Kein Build, kein Framework - OBS laedt die Dateien direkt, und jede Zwischenstufe waere ein Ding, das mitten im Stream kaputtgehen kann. Server-Sent Events statt WebSocket, entgegen der Skizze in chat-control.md: Node bringt einen WebSocket-*Client* mit, aber keinen Server, `EventSource` verbindet sich von allein neu, und die Richtung stimmt - das Overlay hoert nur zu. Gegen die tote Browser-Source nach einem Neustart stehen drei Dinge: der eingebaute Reconnect, ein Herzschlag als echtes Ereignis (ein SSE-Kommentar haelt die Verbindung offen, ist im Browser aber unsichtbar), und ein Zustands-Schnappschuss beim Verbinden. Abos, Raids, Bits und Loeschungen kommen ueber IRC-USERNOTICE und CLEARCHAT herein; das wurde bisher weggeworfen. Follows fehlen weiter, die gibt es nur ueber EventSub. GIFs im Chat: Twitch schickt dafuer einen Tag `gifs`, den wir nicht kannten. gifs=0-22|Pnd7qLFuGCOntZcNKB|https://media0.giphy.com/media/.../giphy.gif PRIVMSG #abdulive_ :[Idk GIF by Respective] Der Nachrichtentext ist nur ein Platzhalter, der Bereich markiert ihn. Ausgewertet wird er jetzt; ohne das stand woertlich "[Idk GIF by Respective]" im Bild. Gefunden wurde der Tag durch einen Rohmitschnitt - in 3094 Nachrichten aus acht grossen Kanaelen war kein einziges GIF, weil die Adresse eben nicht im Text steht. Zwei Fehler, die beim Durchklicken im Browser aufgefallen sind: - Die Aufraeumfunktion im Chat zaehlte Zeilen, die erst nach der Ausblend-Animation aus dem DOM verschwinden, und lief in eine Endlosschleife. In OBS waere die Quelle beim vierzehnten Chatbeitrag eingefroren. - Der Bereichsparser der GIFs war zu nachsichtig: `-1-4` zerfaellt beim Trennen in ['', '1', '4'], und `Number('')` ist 0 - der Bereich saehe gueltig aus und wuerde den falschen Textteil ersetzen. Auf der Uebersichtsseite steht fuer jede Einblendung, jede Chat-Variante und jeden Effekt ein Knopf. Ohne den liesse sich eine Raid-Einblendung nur pruefen, indem man auf einen echten Raid wartet. Was einen Zustand setzt, ist waehrend eines Streams gesperrt; "Stand zuruecksetzen" ausdruecklich nicht, sonst kaeme man aus einem erfundenen Zustand nicht mehr heraus. build-package.ts nimmt jetzt auch html/css/js mit - sonst liefert das Paket 404 statt Overlay. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
3b606e36fb
commit
bc2c8f6cbe
24 files changed
+3221
-8
No files matched your search
@@ -0,0 +1,122 @@
|
||||
/* Gemeinsames Aussehen aller Browser-Sources.
|
||||
*
|
||||
* Zwei Dinge gelten auf jeder Seite und sind der Grund, warum es diese Datei
|
||||
* gibt:
|
||||
*
|
||||
* 1. Der Hintergrund ist durchsichtig. Eine Browser-Source mit weissem
|
||||
* Hintergrund ist der haeufigste Anfaengerfehler, und man sieht ihn erst
|
||||
* in der Aufzeichnung.
|
||||
* 2. Text liegt ueber bewegtem Bild. Reine Farbe reicht dafuer nicht -
|
||||
* jeder Text bekommt eine dunkle Kontur, sonst verschwindet er im hellen
|
||||
* Gameplay. Deshalb `paint-order` und der Schatten unten.
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Twitch-Lila wie im Discord-Bauplan, damit Stream und Server zusammengehoeren. */
|
||||
--lila: #a970ff;
|
||||
--lila-tief: #6441a5;
|
||||
--tuerkis: #4fd1c5;
|
||||
--pink: #ff4fa3;
|
||||
--gold: #ffc53d;
|
||||
--gruen: #4ade80;
|
||||
--rot: #ef4444;
|
||||
|
||||
--tinte: #120e1d;
|
||||
--tinte-klar: rgba(18, 14, 29, .72);
|
||||
--schrift: #f6f3ff;
|
||||
--schrift-leise: #c5bde0;
|
||||
|
||||
--rund: 14px;
|
||||
--schatten: 0 12px 40px rgba(0, 0, 0, .55);
|
||||
--glanz: inset 0 1px 0 rgba(255, 255, 255, .12);
|
||||
|
||||
/* Segoe UI Variable gibt es auf Windows 11 - Abdus Rechner. Der Rest der
|
||||
* Liste ist Rueckfall fuer Entwicklung auf anderen Systemen. */
|
||||
--font: "Segoe UI Variable Display", "Segoe UI", Inter, system-ui, sans-serif;
|
||||
--font-zahl: "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
font-family: var(--font);
|
||||
color: var(--schrift);
|
||||
/* OBS rendert mit eigener Skalierung; ohne das wirken Kanten weich. */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
user-select: none;
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
.kontur {
|
||||
paint-order: stroke fill;
|
||||
-webkit-text-stroke: 4px rgba(0, 0, 0, .55);
|
||||
text-shadow: 0 2px 10px rgba(0, 0, 0, .7);
|
||||
}
|
||||
|
||||
/* Glasplatte: der Traeger fuer alles, was ueber dem Spiel steht. */
|
||||
.glas {
|
||||
background: var(--tinte-klar);
|
||||
backdrop-filter: blur(14px) saturate(140%);
|
||||
border: 1px solid rgba(255, 255, 255, .1);
|
||||
border-radius: var(--rund);
|
||||
box-shadow: var(--schatten), var(--glanz);
|
||||
}
|
||||
|
||||
/* Der Lichtstreifen, der einmal ueber eine Flaeche wandert. Wird von den
|
||||
* Einblendungen benutzt und ist der Grund, warum eine Einblendung "teuer"
|
||||
* aussieht, ohne dass ein Video dahintersteckt. */
|
||||
@keyframes streifen {
|
||||
from { transform: translateX(-120%) skewX(-18deg); }
|
||||
to { transform: translateX(320%) skewX(-18deg); }
|
||||
}
|
||||
|
||||
.streifen::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0 auto 0 0;
|
||||
width: 28%;
|
||||
background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .3), transparent);
|
||||
animation: streifen 1.5s cubic-bezier(.3, 0, .2, 1) .35s both;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes pulsieren {
|
||||
0%, 100% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: .55; transform: scale(.82); }
|
||||
}
|
||||
|
||||
/* Zum Ansehen im normalen Browser: ?probe=1 legt einen dunklen Grund unter
|
||||
* die Seite. Ohne den steht heller Text auf Weiss, und man sieht nichts -
|
||||
* in OBS liegt das Overlay ueber dem Spiel, im Browser ueber gar nichts. */
|
||||
body.probe {
|
||||
background:
|
||||
radial-gradient(60% 60% at 30% 25%, #2a1f45, transparent 70%),
|
||||
radial-gradient(50% 50% at 75% 70%, #123c3a, transparent 70%),
|
||||
#0b0912;
|
||||
}
|
||||
|
||||
/* Wer im Browser nachsieht, will nicht raten, ob die Verbindung steht.
|
||||
* In OBS ist der Punkt unsichtbar, weil er nur bei Verlust erscheint. */
|
||||
.getrennt {
|
||||
position: fixed;
|
||||
right: 10px;
|
||||
bottom: 8px;
|
||||
font: 500 12px/1 var(--font-zahl);
|
||||
color: var(--rot);
|
||||
background: rgba(0, 0, 0, .7);
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
opacity: 0;
|
||||
transition: opacity .4s;
|
||||
}
|
||||
body.offline .getrennt { opacity: 1; }
|
||||
|
||||
/* Wer mit prefers-reduced-motion arbeitet, bekommt in OBS trotzdem die
|
||||
* Animationen - eine Browser-Source hat keinen Menschen mit Vestibular-
|
||||
* problemen davor. Die Einstellung wird hier bewusst nicht beachtet. */
|
||||
Reference in new issue
Block a user