Pult: Stream-PC per Tipp freigeben, Sound-Quelle legt er selbst in OBS an
Paket bauen und veroeffentlichen / paket (push) Successful in 42s
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:
1 parent
32416d1916
commit
54dbe1265b
15 files changed
+675
-50
No files matched your search
@@ -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`.
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in new issue
Block a user