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.
| Overlay | Rôle |
|---|---|
timer.streamoos | Compte à rebours avec variantes de thème |
radio.streamoos | Radio : pochette + titre/artiste de la source choisie dans Musique (KHInsider, lecteur système) |
twitch-alerts.streamoos | Alertes Twitch (follow/sub/raid/cheer/gift_sub) avec effet shiny optionnel |
twitch-events-ribbon.streamoos | Bandeau scrolling des derniers events - variantes de position ci-dessous |
twitch-shoutout.streamoos | Shoutout : chaîne mise en avant par /shoutout (avatar, dernière catégorie) |
twitch-goal-bar.streamoos | Barre d'objectif remplie par les compteurs live (follows, subs, bits, viewers…) |
spectrum-analyzer.streamoos | Visualizer musique léger (28 barres, modes pulse/wave) |
dock-obs.streamoos | Dock 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
Dans OBS, clique + → Navigateur
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)Résolution recommandée : 1920×1080 ou la taille de ta scène
Active "Actualiser le navigateur quand la scène devient active"
L'overlay se connecte automatiquement à
ws://127.0.0.1:8765au 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 (tableoverlay_composite_presets) et lu via la commande WSoverlay_composite/get_preset. Les presets se créent/éditent viawindow.streamoos.sendCommand(IPC renderer privilégié) -save_preset/delete_presetne sont volontairement pas atteignables depuis le WS overlay orienté réseau, commetwitch/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=1bascule leStreamooSClientde 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êmepositionne se superposent jamais : chacun appellerequestOverlaySlot(position, durationMs)(depuisstreamoos-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 overlayskind:"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.
<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
new StreamooSClient(wsUrl, options);| Option | Défaut | Description |
|---|---|---|
wsUrl | ws://localhost:8765 | URL du serveur WS |
reconnectBaseDelayMs | 1000 | Délai initial de reconnexion |
reconnectMaxDelayMs | 15000 | Délai maximum de reconnexion |
reconnectJitterMs | 250 | Jitter aléatoire ajouté au délai |
connectTimeoutMs | 5000 | Timeout de connexion |
autoConnect | true | Connexion automatique à l'instanciation |
Événements disponibles
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
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.
| Overlay | Themes |
|---|---|
| KHInsider | streamoos, ghibli, xp, glass, noisy, minimal-dark |
| Timer | streamoos, minimal-dark |
| SMTC | streamoos, minimal-dark |
Position de l'overlay
Tous les overlays supportent 9 positions d'ancrage :
| Haut | Milieu | Bas |
|---|---|---|
top-left · top-center · top-right | middle-left · center · middle-right | bottom-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 :
| Valeur | Disposition |
|---|---|
| omis | Bandeau ondulé original 1920×1080 |
corner-top-left · corner-top-right · corner-bottom-left · corner-bottom-right | Ribbon compact à 45 % ancré dans un coin |
edge-left · edge-right | Pivoté 90° pour défiler verticalement le long d'un bord |
band-top · band-bottom | Bandeau 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ètre | Défaut | Description |
|---|---|---|
metric | follows | Compteur suivi, voir le tableau ci-dessous |
target | 50 | Objectif, entier positif |
label | libellé auto | Texte affiché à gauche, 60 caractères max |
onReached | celebrate | freeze (bar pleine), celebrate (pulsation), next (objectif suivant) |
step | = target | Incrément utilisé par onReached=next |
position | bottom-center | top-left · top-center · top-right · bottom-left · bottom-center · bottom-right |
theme | neon | neon · streamoos |
accent | #9147ff | Couleur 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.
metric | Portée | Source |
|---|---|---|
follows · subscriptions · giftSubs · cheerBits · raids | Session | Événements EventSub de la session en cours |
totalFollowers · totalSubs | Total | Sondage Helix (compte de la chaîne) |
viewersNow | Instant | Sondage 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ètre | Défaut | Description |
|---|---|---|
bars | 28 | Nombre de barres de fréquence (4–64) |
color | #00ff88 | Couleur des barres (hex) |
mode | pulse | pulse (animé sur le beat) ou wave (sinusoïdal) |
sensitivity | 5 | Multiplicateur d'amplitude (1–10) |
Configuration via WebSocket
{
"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 importesaddCustomOverlay()-- importer un nouvel overlay HTMLremoveCustomOverlay(id)-- supprimer un overlay personnaliseopenCustomOverlay(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 :
<!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 :
| Origine | Contexte |
|---|---|
null | OBS Browser Source (fichier local) |
file:// | Electron production |
http://127.0.0.1:5173 | Vite dev server |
Toute autre origine est rejetée avec HTTP 403.
