Skip to content

Overlays OBS ​

Les overlays sont des fichiers HTML/CSS/JS vanilla situés dans app/overlays/. Ils se connectent au runtime StreamooS via WebSocket et s'utilisent comme Browser Sources dans OBS.

Overlays disponibles ​

Les overlays built-in vivent sous app/overlays/builtin/<id>.streamoos/. Chacun expose un manifest.json (auto-découvert par overlay-discovery.ts), un HTML d'entrée, du CSS et du JS.

OverlayRôle
timer.streamoosCompte à rebours avec variantes de thème
radio.streamoosRadio : pochette + titre/artiste de la source choisie dans Musique (KHInsider, lecteur système)
twitch-alerts.streamoosAlertes Twitch (follow/sub/raid/cheer/gift_sub) avec effet shiny optionnel
twitch-events-ribbon.streamoosBandeau scrolling des derniers events - variantes de position ci-dessous
twitch-shoutout.streamoosShoutout : chaîne mise en avant par /shoutout (avatar, dernière catégorie)
twitch-goal-bar.streamoosBarre d'objectif remplie par les compteurs live (follows, subs, bits, viewers…)
spectrum-analyzer.streamoosVisualizer musique léger (28 barres, modes pulse/wave)
dock-obs.streamoosDock OBS minimaliste 3 vues (Music / Timer / Chat)

Les assets uploadés par l'utilisateur (images d'alertes custom…) sont stockés en SQLite et servis par le serveur HTTP overlay à l'adresse http://127.0.0.1:8766/overlays/asset/<id> - le protocole streamoos-asset:// n'est dispo que côté renderer Electron, donc les Browser Sources OBS passent par cette route HTTP. Les overlays JS réécrivent automatiquement les URI streamoos-asset://<id> vers ce chemin (twitch_alerts.js#resolveAssetPath).

Ajouter un overlay dans OBS ​

  1. Dans OBS, clique + → Navigateur

  2. Décoche "URL locale" et entre le chemin absolu :

    file:///C:/Users/toi/StreamooS/app/overlays/timer/index.html

    (Linux : file:///home/toi/StreamooS/app/overlays/timer/index.html)

  3. Résolution recommandée : 1920×1080 ou la taille de ta scène

  4. Active "Actualiser le navigateur quand la scène devient active"

L'overlay se connecte automatiquement à ws://127.0.0.1:8765 au chargement. Pas de configuration supplémentaire.

Mode composite (plusieurs overlays, une seule source OBS) ​

Le mode une-URL-par-overlay ci-dessus fonctionne toujours à l'identique et reste le défaut. En alternative, une source composite embarque plusieurs overlays choisis derrière une seule source navigateur OBS :

http://127.0.0.1:8766/overlays/composite/?preset=<id>
  • Un preset (id, name, liste de {overlaySlug, kind: "permanent" | "event", position}) est stocké côté serveur (table overlay_composite_presets) et lu via la commande WS overlay_composite/get_preset. Les presets se créent/éditent via window.streamoos.sendCommand (IPC renderer privilégié) - save_preset/delete_preset ne sont volontairement pas atteignables depuis le WS overlay orienté réseau, comme twitch/stream:save_preset.
  • Chaque overlay embarqué tourne dans son propre <iframe src="../builtin/<slug>?composite=1"> - il se positionne lui-même exactement comme en source unique. La page composite ne déplace jamais un iframe.
  • ?composite=1 bascule le StreamooSClient de cet overlay en mode proxy : aucune connexion propre, il relaie via l'unique connexion réelle du parent (voir plus bas).
  • Deux overlays kind:"event" configurés à la même position ne se superposent jamais : chacun appelle requestOverlaySlot(position, durationMs) (depuis streamoos-client.js) avant d'afficher un item transitoire et attend son tour (FIFO, rien n'est perdu) si un autre est déjà affiché à cette position. Les overlays kind:"permanent" (radio, timer, ribbon) n'attendent jamais.

Raisonnement complet et ce qui est explicitement hors scope pour l'instant (UI d'édition des presets, fondu de cession permanent-vers-événementiel) : doc/internal/adr/ADR-010-overlay-composite-mode.md.

Client WebSocket partagé (StreamooSClient) ​

Tous les overlays utilisent app/overlays/shared/websocket-client.js - une classe réutilisable qui gère la connexion, la reconnexion automatique, et la réception des updates.

html
<script src="../shared/websocket-client.js"></script>
<script>
  const client = new StreamooSClient("ws://127.0.0.1:8765");

  // Recevoir les mises à jour d'état
  client.onUpdate((msg) => {
    if (msg.feature === "timer") {
      const { remainingSeconds, running } = msg.data;
      // mettre à jour le DOM
    }
  });

  // Envoyer une commande
  client.sendCommand("timer", "start", { minutes: 5, seconds: 0 });
</script>

Options du constructeur ​

js
new StreamooSClient(wsUrl, options);
OptionDéfautDescription
wsUrlws://localhost:8765URL du serveur WS
reconnectBaseDelayMs1000Délai initial de reconnexion
reconnectMaxDelayMs15000Délai maximum de reconnexion
reconnectJitterMs250Jitter aléatoire ajouté au délai
connectTimeoutMs5000Timeout de connexion
autoConnecttrueConnexion automatique à l'instanciation

Événements disponibles ​

js
client.on("connected", () => {
  /* connecté */
});
client.on("disconnected", ({ willReconnect }) => {
  /* déconnecté */
});
client.on("update", (msg) => {
  /* msg.feature, msg.data */
});
client.on("response", (msg) => {
  /* réponse à une commande */
});
client.on("error", (msg) => {
  /* erreur serveur */
});

Méthodes ​

js
client.sendCommand(feature, action, data); // envoyer une commande
client.send(rawObject); // envoyer un objet brut
client.disconnect(); // déconnexion manuelle (pas de reconnexion)

Reconnexion automatique ​

Le client implémente un backoff exponentiel avec jitter :

  • 1ʳᵉ tentative : ~1s
  • Progression : doublement + jitter jusqu'à 15s max
  • Reconnexion infinie jusqu'à disconnect() explicite

Themes d'overlay ​

Chaque overlay supporte plusieurs themes visuels. Les themes sont configures via l'UI du dashboard ou en envoyant une commande set_overlay_config via WebSocket.

OverlayThemes
KHInsiderstreamoos, ghibli, xp, glass, noisy, minimal-dark
Timerstreamoos, minimal-dark
SMTCstreamoos, minimal-dark

Position de l'overlay ​

Tous les overlays supportent 9 positions d'ancrage :

HautMilieuBas
top-left · top-center · top-rightmiddle-left · center · middle-rightbottom-left · bottom-center · bottom-right

Twitch Events Ribbon - variantes de placement ​

L'overlay ribbon accepte un paramètre ?position= dans l'URL pour l'épingler à un coin ou un bord plutôt que la courbe pleine-toile par défaut :

ValeurDisposition
omisBandeau ondulé original 1920×1080
corner-top-left · corner-top-right · corner-bottom-left · corner-bottom-rightRibbon compact à 45 % ancré dans un coin
edge-left · edge-rightPivoté 90° pour défiler verticalement le long d'un bord
band-top · band-bottomBandeau horizontal compressé contre le bord choisi

Ajoute la valeur dans l'URL lors de la config Browser Source OBS, ex. …/twitch-events-ribbon.streamoos/twitch_events_ribbon.html?position=edge-left.

Twitch Goal Bar - config par URL ​

twitch-goal-bar.streamoos accepte les paramètres suivants :

ParamètreDéfautDescription
metricfollowsCompteur suivi, voir le tableau ci-dessous
target50Objectif, entier positif
labellibellé autoTexte affiché à gauche, 60 caractères max
onReachedcelebratefreeze (bar pleine), celebrate (pulsation), next (objectif suivant)
step= targetIncrément utilisé par onReached=next
positionbottom-centertop-left · top-center · top-right · bottom-left · bottom-center · bottom-right
themeneonneon · streamoos
accent#9147ffCouleur hex de la barre

Session ou total, ce n'est pas le même nombre. « 40 follows ce soir » et « 1000 followers au total » sont deux métriques différentes ; le libellé automatique le précise, un libellé custom ne le fera pas à ta place.

metricPortéeSource
follows · subscriptions · giftSubs · cheerBits · raidsSessionÉvénements EventSub de la session en cours
totalFollowers · totalSubsTotalSondage Helix (compte de la chaîne)
viewersNowInstantSondage Helix

Les métriques total* et viewersNow restent à zéro hors live : le sondage Helix ne tourne que pendant un stream.

Spectrum Analyzer - config par URL ​

spectrum-analyzer.streamoos accepte les paramètres suivants :

ParamètreDéfautDescription
bars28Nombre de barres de fréquence (4–64)
color#00ff88Couleur des barres (hex)
modepulsepulse (animé sur le beat) ou wave (sinusoïdal)
sensitivity5Multiplicateur d'amplitude (1–10)

Configuration via WebSocket ​

json
{
  "type": "command",
  "feature": "smtc",
  "action": "set_overlay_config",
  "data": {
    "enabled": true,
    "radioSource": "auto",
    "position": "bottom-right",
    "showArtwork": true,
    "showProgress": true,
    "theme": "glass"
  }
}

Overlays personnalises ​

StreamooS supporte l'importation d'overlays HTML personnalises via le dashboard. Les overlays personnalises sont stockes dans le repertoire userData de l'app et peuvent etre geres via le pont preload :

  • listCustomOverlays() -- lister tous les overlays importes
  • addCustomOverlay() -- importer un nouvel overlay HTML
  • removeCustomOverlay(id) -- supprimer un overlay personnalise
  • openCustomOverlay(id) -- ouvrir dans une fenetre externe

Les overlays personnalises se connectent au meme endpoint ws://127.0.0.1:8765 et peuvent utiliser app/overlays/shared/websocket-client.js.

Creer un overlay custom ​

Structure minimale :

html
<!doctype html>
<html lang="fr">
  <head>
    <meta charset="UTF-8" />
    <style>
      body {
        background: transparent;
        margin: 0;
      }
      /* style OBS-friendly */
    </style>
  </head>
  <body>
    <div id="display">Connexion...</div>

    <script src="../shared/websocket-client.js"></script>
    <script>
      const client = new StreamooSClient();

      client.on("connected", () => {
        document.getElementById("display").textContent = "Connecté";
        client.sendCommand("timer", "get_state");
      });

      client.on("update", (msg) => {
        if (msg.feature !== "timer") return;
        const { remainingSeconds } = msg.data;
        const m = Math.floor(remainingSeconds / 60)
          .toString()
          .padStart(2, "0");
        const s = (remainingSeconds % 60).toString().padStart(2, "0");
        document.getElementById("display").textContent = `${m}:${s}`;
      });
    </script>
  </body>
</html>

Origines WebSocket autorisées ​

Le serveur valide l'en-tête Origin à chaque connexion :

OrigineContexte
nullOBS Browser Source (fichier local)
file://Electron production
http://127.0.0.1:5173Vite dev server

Toute autre origine est rejetée avec HTTP 403.

Released under the MIT License.