Zwei Fehler aus dem Betrieb: fehlender Import, geschlossenes stdin
Beide aus dem Serverlog vom 28.08.2026, beide meine. 1. `getStation is not defined` bei jedem /api/radio/status, sobald etwas lief. Die Funktion stand in api.js im Code und in keinem Import. Weder `node --check` noch das Laden des Moduls sieht das: ESM prueft beim Verlinken nur, ob die IMPORTIERTEN Namen in der Quelle existieren, nicht ob die BENUTZTEN importiert sind. Mein API-Testlauf kam nie an die Zeile, weil dort nie etwas lief -- genau die Luecke, die ich beim Ausliefern als "nicht geprueft" benannt hatte. Ein Pruefer dafuer liegt jetzt im Scratchpad und meldet fuer src/ null Treffer. Er hat zwei Gegenproben: ein eingebauter Aufruf ohne Import muss gefunden werden, ein dynamisch importierter darf NICHT gemeldet werden. Seine ersten beiden Fassungen haben Fehlalarm geschlagen (14 bzw. 11 Treffer, alle dynamische Importe) -- ein Pruefer, der Richtiges als falsch meldet, ist so wertlos wie einer, der nichts sieht. 2. `Cannot read properties of null (reading 'on')` in tonquelle, direkt gefolgt von `ffmpeg: pipe:0: Invalid data found when processing input`. `wandler` startete ffmpeg immer mit stdio ['ignore','pipe','pipe'] -- stdin also ZU. Fuer YouTube bekommt ffmpeg aber `-i pipe:0`. Damit las es aus /dev/null, und `ff.stdin` war null, woran schon das Anhaengen der Fehlerbehandlung zerbrach. Nachgestellt und bestaetigt: dieselbe stdio-Form liefert stdin === null, mit 'pipe' eine Rohrleitung. stdin ist jetzt offen, wenn die Eingabe `pipe:0` ist. Und `tonquelle` prueft die Rohrenden, bevor es sie anfasst: startet ein Prozess nicht, gibt es eine Meldung statt eines TypeErrors, der die ganze Interaktion mitreisst.
This commit is contained in:
+20
-2
@@ -177,8 +177,14 @@ export async function titelHolen(url, { timeoutMs = 8000, bloecke = 3 } = {}) {
|
|||||||
* ihn sonst endgültig beenden. Bei einer Rohrleitung wäre dieselbe Option
|
* ihn sonst endgültig beenden. Bei einer Rohrleitung wäre dieselbe Option
|
||||||
* sinnlos — es gibt nichts, wohin sich neu verbinden liesse.
|
* sinnlos — es gibt nichts, wohin sich neu verbinden liesse.
|
||||||
*
|
*
|
||||||
|
* `netz` entscheidet ausserdem, ob stdin offen ist, und das ist keine
|
||||||
|
* Feinheit: bei `-i pipe:0` MUSS stdin eine Rohrleitung sein. Stand hier
|
||||||
|
* `ignore` (wie es bis zum 28.08.2026 der Fall war), zeigt `pipe:0` auf
|
||||||
|
* /dev/null — ffmpeg meldet dann „Invalid data found when processing input",
|
||||||
|
* und `ff.stdin` ist `null`, woran der Aufbau der Kette vorher zerbrach.
|
||||||
|
*
|
||||||
* @param {string} eingabe Adresse oder `pipe:0`
|
* @param {string} eingabe Adresse oder `pipe:0`
|
||||||
* @param {{netz: boolean}} opts
|
* @param {{netz: boolean}} opts netz=true: ffmpeg holt selbst; false: es liest aus stdin
|
||||||
*/
|
*/
|
||||||
function wandler(eingabe, { netz }) {
|
function wandler(eingabe, { netz }) {
|
||||||
const ff = spawn(FFMPEG, [
|
const ff = spawn(FFMPEG, [
|
||||||
@@ -195,7 +201,8 @@ function wandler(eingabe, { netz }) {
|
|||||||
'-f', 's16le', '-acodec', 'pcm_s16le',
|
'-f', 's16le', '-acodec', 'pcm_s16le',
|
||||||
'-ar', '48000', '-ac', '2',
|
'-ar', '48000', '-ac', '2',
|
||||||
'pipe:1',
|
'pipe:1',
|
||||||
], { stdio: ['ignore', 'pipe', 'pipe'] });
|
// Kein stdin bei einer Adresse, eine Rohrleitung bei `pipe:0`.
|
||||||
|
], { stdio: [netz ? 'ignore' : 'pipe', 'pipe', 'pipe'] });
|
||||||
// Ohne Zuhörer auf stderr läuft die Pipe voll und ffmpeg bleibt stehen
|
// Ohne Zuhörer auf stderr läuft die Pipe voll und ffmpeg bleibt stehen
|
||||||
ff.stderr.on('data', (d) => {
|
ff.stderr.on('data', (d) => {
|
||||||
const text = d.toString().trim();
|
const text = d.toString().trim();
|
||||||
@@ -223,6 +230,17 @@ function tonquelle(quelle) {
|
|||||||
}
|
}
|
||||||
const yt = tonstrom(quelle.titel.url);
|
const yt = tonstrom(quelle.titel.url);
|
||||||
const ff = wandler('pipe:0', { netz: false });
|
const ff = wandler('pipe:0', { netz: false });
|
||||||
|
// Startet ein Prozess nicht, sind seine Rohrenden `null`. Ohne diese
|
||||||
|
// Prüfung wirft schon das Anhängen der Fehlerbehandlung einen
|
||||||
|
// TypeError — und der reisst die ganze Interaktion mit, statt dass
|
||||||
|
// jemand „kein Ton" zu sehen bekommt.
|
||||||
|
if (!yt.stdout || !ff.stdin) {
|
||||||
|
yt.kill('SIGKILL');
|
||||||
|
ff.kill('SIGKILL');
|
||||||
|
throw new Error('Tonkette liess sich nicht aufbauen — '
|
||||||
|
+ `yt-dlp: ${yt.stdout ? 'ok' : 'kein Ausgang'}, `
|
||||||
|
+ `ffmpeg: ${ff.stdin ? 'ok' : 'kein Eingang'}.`);
|
||||||
|
}
|
||||||
yt.stdout.on('error', () => {});
|
yt.stdout.on('error', () => {});
|
||||||
ff.stdin.on('error', () => {});
|
ff.stdin.on('error', () => {});
|
||||||
yt.stdout.pipe(ff.stdin);
|
yt.stdout.pipe(ff.stdin);
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ import {
|
|||||||
createService, updateService, listServices, deleteService,
|
createService, updateService, listServices, deleteService,
|
||||||
savePage, getPage, listPages, listPublishedPages, deletePage,
|
savePage, getPage, listPages, listPublishedPages, deletePage,
|
||||||
lsState, lsModSizes, setLsModSize,
|
lsState, lsModSizes, setLsModSize,
|
||||||
listStations, createStation, updateStation, deleteStation,
|
listStations, getStation, createStation, updateStation, deleteStation,
|
||||||
queueList, queueRemove, queueClear, queueReorder, queueVor, queueStand,
|
queueList, queueRemove, queueClear, queueReorder, queueVor, queueStand,
|
||||||
setRadioState, clearRadioState, radioState,
|
setRadioState, clearRadioState, radioState,
|
||||||
} from '../db.js';
|
} from '../db.js';
|
||||||
|
|||||||
Reference in New Issue
Block a user