Pult: Stream-PC per Tipp freigeben, Sound-Quelle legt er selbst in OBS an
Paket bauen und veroeffentlichen / paket (push) Successful in 42s

- ingest wuerfelt beim ersten Start einen Schluessel und meldet sich beim
  Hub; der antwortet 202, bis im Pult jemand auf Freigeben tippt
- nach dem Verbinden schickt der Hub die Adresse von /sounds, ingest legt
  Szene "abdulive Ton" mit der Browser-Source an und haengt sie in jede Szene
- fern:verbinden bleibt als Weg von Hand

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZeasyAlexandClaude Opus 5.5 committed 2026-10-26 13:03:06 +01:00
1 parent 32416d1916
commit 54dbe1265b
15 files changed
+675 -50

No files matched your search

+24 -7
View File
@@ -114,15 +114,32 @@ 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`). Einmal auf dem Stream-PC:
`apps/overlay-server/src/fern.ts`). In OBS muss nur obs-websocket an sein -
dasselbe, was `!clip` braucht.
```
abdulive fern:verbinden https://abdu.dimension47.de <schlüssel>
```
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 <adresse> <schlüssel>` bleibt
als Weg von Hand (Befehl auf der Übersicht).
Der fertige Befehl steht auf der Übersicht unter „Stream-PC verbinden“.
Danach `abdulive ingest` neu starten. Jeder Knopf wartet auf die Antwort von
OBS und sagt ehrlich, wenn es nicht ging.
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`.
+11
View File
@@ -278,6 +278,17 @@ main {
.ton-zeile.stumm .ton-stand { background: rgba(239, 68, 68, .16); color: #ffb3b3; }
.ton-zeile.stumm svg { color: #ffb3b3; }
.anfragen { display: grid; gap: 12px; margin-bottom: 4px; }
.anfrage {
border-radius: var(--rund); padding: 16px; margin-bottom: 12px;
background: rgba(169, 112, 255, .1); border: 1px solid var(--lila);
}
.anfrage h2 { font-size: 18px; margin: 0 0 4px; }
.anfrage p { margin: 0 0 14px; color: var(--leise); font-size: 14px; }
.anfrage .reihe { display: flex; gap: 8px; }
.anfrage .reihe .primaer { flex: 1; min-height: 52px; font-size: 16px; }
.knopf.leise { margin-top: 28px; background: transparent; color: var(--leise); border-color: var(--linie); font-weight: 500; }
.leer-karte { text-align: center; padding: 28px 18px; }
.leer-karte h2 { font-size: 18px; margin: 0 0 8px; }
.leer-karte p { color: var(--leise); margin: 0; font-size: 14px; }
+4
View File
@@ -66,6 +66,7 @@
<!-- ======================================================== Szenen -->
<section id="tab-szenen" class="tab" aria-labelledby="nav-szenen">
<div id="anfragen" class="anfragen"></div>
<div id="obs-fehlt" class="karte leer-karte" hidden>
<h2 id="obs-fehlt-titel">Stream-PC nicht verbunden</h2>
<p id="obs-fehlt-text"></p>
@@ -83,6 +84,8 @@
<h3 class="abschnitt">Ton</h3>
<div id="ton" class="ton"></div>
<button id="trennen" class="knopf breit leise" type="button">Stream-PC trennen</button>
</div>
</section>
@@ -140,6 +143,7 @@
<button id="nav-szenen" data-tab="szenen" type="button">
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="2.5" y="5" width="19" height="13" rx="2"/><path d="M8 21h8"/></svg>
Szenen
<i id="nav-fern" class="punkt" hidden></i>
</button>
<button id="nav-stream" data-tab="stream" type="button">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 20V10M10 20V4M16 20v-7M22 20H2"/></svg>
+58 -2
View File
@@ -369,8 +369,8 @@
$('obs-da').hidden = fehlt;
if (!o.pc) {
$('obs-fehlt-titel').textContent = 'Stream-PC nicht verbunden';
$('obs-fehlt-text').textContent = 'Auf dem Stream-PC muss abdulive ingest laufen und einmal mit ' +
'„abdulive fern:verbinden …“ eingerichtet sein. Der Befehl steht auf der Übersicht unter „Stream-PC verbinden“.';
$('obs-fehlt-text').textContent = 'Sobald abdulive auf dem Stream-PC läuft, meldet er sich hier ' +
'und du tippst einmal auf „Freigeben“. Läuft er schon, ist er vielleicht aus oder offline.';
} else if (!o.obs) {
$('obs-fehlt-titel').textContent = 'OBS ist nicht erreichbar';
$('obs-fehlt-text').textContent = 'Der Stream-PC ist da, aber OBS nicht. Läuft OBS, und ist ' +
@@ -436,6 +436,60 @@
obsRuf(b, { was: 'stumm', quelle: b.dataset.quelle, stumm: b.dataset.stumm === '1' ? '0' : '1' });
});
// ------------------------------------------------------------ Freigabe
// Ein Stream-PC, der sich zum ersten Mal meldet, wartet hier auf einen
// Tipp. Name und Adresse kommen vom PC selbst - eine Anfrage, die man nicht
// erwartet, lehnt man ab.
function zeigeAnfragen(liste) {
var box = $('anfragen');
box.textContent = '';
$('nav-fern').hidden = !liste.length;
liste.forEach(function (a) {
var k = el('div', 'anfrage');
k.appendChild(el('h2', '', 'Stream-PC „' + a.name + '“ möchte sich verbinden'));
var seit = new Date(a.seit);
k.appendChild(el('p', '', 'Von ' + a.adresse + ', seit ' +
seit.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) +
' Uhr. Danach steuert das Pult OBS auf diesem Rechner.'));
var reihe = el('div', 'reihe');
var ja = el('button', 'knopf primaer', 'Freigeben');
ja.type = 'button'; ja.dataset.was = 'freigeben'; ja.dataset.id = a.id;
var nein = el('button', 'knopf', 'Ablehnen');
nein.type = 'button'; nein.dataset.was = 'ablehnen'; nein.dataset.id = a.id;
reihe.appendChild(ja); reihe.appendChild(nein);
k.appendChild(reihe);
box.appendChild(k);
});
}
function ladeAnfragen() {
holen('/pult/fern').then(function (b) { zeigeAnfragen(b.anfragen || []); }, function () { /* still */ });
}
$('anfragen').addEventListener('click', function (e) {
var b = e.target.closest('button[data-was]');
if (!b) return;
tippen();
mitWarten(b, rufen('/pult/fern', { was: b.dataset.was, id: b.dataset.id })).then(function (r) {
melden(r.text, r.ok ? 'ok' : 'fehler');
if (r.anfragen) zeigeAnfragen(r.anfragen);
});
});
$('trennen').addEventListener('click', function () {
var b = $('trennen');
if (!b.dataset.sicher) {
b.dataset.sicher = '1';
b.textContent = 'Wirklich trennen? Danach neu freigeben.';
setTimeout(function () { b.dataset.sicher = ''; b.textContent = 'Stream-PC trennen'; }, 4000);
return;
}
b.dataset.sicher = '';
b.textContent = 'Stream-PC trennen';
rufen('/pult/fern', { was: 'trennen' }).then(function (r) { melden(r.text, r.ok ? 'ok' : 'fehler'); });
});
// ------------------------------------------------------------ Liegestuetze
function zeigeLz(st) {
@@ -581,6 +635,7 @@
case 'sound': knall(ev.id); break;
case 'sounds-geaendert': ladeSounds(); break;
case 'tts': ladeWartend(); break;
case 'fern-anfrage': ladeAnfragen(); break;
}
};
}
@@ -611,6 +666,7 @@
ladeWartend();
}, function () { /* abgemeldet oder weg - zeigt sich oben */ });
ladeSounds();
ladeAnfragen();
verbinde();
wachHolen();