From 1811b3281d0f9e652b465a9a6c83fea86f03d157 Mon Sep 17 00:00:00 2001 From: chk <79915315+ChKendel@users.noreply.github.com> Date: Sat, 6 Jun 2026 10:49:42 +0200 Subject: [PATCH] Multicam (c) buffer --- src/cameraSwitch.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/cameraSwitch.js b/src/cameraSwitch.js index ab31bbf..21f4b50 100644 --- a/src/cameraSwitch.js +++ b/src/cameraSwitch.js @@ -200,11 +200,21 @@ class CameraSwitch extends EventEmitter { }, 1500); } - // ── HD-Grab: Live sauber stoppen → 1280 greifen → Live zurück ────────────── - // Garantie: zwischen Stop und 1280-Start liegt das `close`-Event des Live- + // ── HD-Grab: Live sauber stoppen → hires greifen → Live zurück ────────────── + // Garantie: zwischen Stop und hires-Start liegt das `close`-Event des Live- // FFmpeg → /dev/videoN ist frei. Niemals zwei Encoder gleichzeitig. + // + // minWidth wird automatisch aus hiresSize abgeleitet (90 % der Soll-Breite), + // damit Frames die noch auf der alten Live-Auflösung basieren abgelehnt werden. + // Beispiel: hiresSize="1920x1080" → minWidth=1728 → lehnt 1280er-Frames ab. async grabHires(opts = {}) { - const { minSize = 15000, minWidth = 1000, settleFrames = 6, maxWaitMs = 6000 } = opts; + const hiresW = parseInt(this.hiresSize.split('x')[0], 10); + const { + minSize = 15000, + minWidth = Math.floor(hiresW * 0.9), // nur Frames bei (fast) der angeforderten Breite + settleFrames = 6, + maxWaitMs = 10000, // mehr Zeit: Kamera braucht nach Format-Wechsel länger + } = opts; if (this.lock) throw new Error('HD-Grab läuft bereits'); this.lock = true; const t0 = Date.now(); @@ -213,12 +223,19 @@ class CameraSwitch extends EventEmitter { try { // 1. Live-FFmpeg beenden, auf Prozess-Ende warten (= Device-FD frei) await this._killCurrentAndWait(); - this.state = 'grabbing'; - console.log(`[cam ${this.id}] HD: Live gestoppt nach ${Date.now() - t0}ms, Gerät frei → 1280-Grab`); - // 2. 1280-FFmpeg starten, warmlaufen lassen, besten Frame greifen + // Kurze Pause: v4l2-Buffer der Kamera können noch Frames der alten Live- + // Auflösung enthalten (z.B. 640×480-Rest wenn hires 1920×1080 fordert). + // 300 ms genügen damit die Kamera den Format-Reset abschliessen kann. + await sleep(300); + + this.state = 'grabbing'; + console.log(`[cam ${this.id}] HD: Live gestoppt nach ${Date.now() - t0}ms, Gerät frei → ${this.hiresSize}-Grab (minWidth=${minWidth})`); + + // 2. hires-FFmpeg starten, warmlaufen lassen, besten Frame greifen const jpeg = await this._captureHires({ minSize, minWidth, settleFrames, maxWaitMs }); - console.log(`[cam ${this.id}] HD OK – ${jpeg.length} bytes, Breite=${readJpegWidth(jpeg) ?? '?'} (${Date.now() - t0}ms)`); + const gotW = readJpegWidth(jpeg) ?? '?'; + console.log(`[cam ${this.id}] HD OK – ${jpeg.length} bytes, Breite=${gotW}px (Soll: ${hiresW}px, ${Date.now() - t0}ms)`); return jpeg; } finally { // 3. Zurück auf Live, sofern noch Verbraucher da sind (On-Demand). Live hat Priorität.