Multicam (c) fix 3
This commit is contained in:
@@ -77,7 +77,7 @@ class MpjpegParser {
|
||||
//
|
||||
// Events: 'frame' (Buffer) – je ein Live-JPEG
|
||||
class CameraSwitch extends EventEmitter {
|
||||
constructor({ id, device, liveSize = '640x480', liveFps = 30, hiresSize = '1280x960', hiresFps = 15, encode = 'copybsf', onDemand = true, idleGraceMs = 15000 }) {
|
||||
constructor({ id, device, liveSize = '640x480', liveFps = 30, hiresSize = '1280x960', hiresFps = 15, encode = 'copybsf', hiresEncode, onDemand = true, idleGraceMs = 15000 }) {
|
||||
super();
|
||||
this.setMaxListeners(0); // beliebig viele Stream-Clients
|
||||
this.id = id;
|
||||
@@ -86,7 +86,8 @@ class CameraSwitch extends EventEmitter {
|
||||
this.liveFps = liveFps;
|
||||
this.hiresSize = hiresSize;
|
||||
this.hiresFps = hiresFps;
|
||||
this.encode = encode; // 'copybsf' (Default, niedrige CPU) | 'mjpeg' (Re-Encode)
|
||||
this.encode = encode; // für Live: 'copybsf' (Default) | 'mjpeg' (Re-Encode)
|
||||
this.hiresEncode = hiresEncode ?? encode; // für Grab: fällt auf encode zurück wenn nicht gesetzt
|
||||
this.onDemand = onDemand; // Live nur laufen lassen, solange Verbraucher da sind
|
||||
this.idleGraceMs = idleGraceMs; // Karenz nach letztem Verbraucher vor dem Stop
|
||||
|
||||
@@ -200,20 +201,27 @@ class CameraSwitch extends EventEmitter {
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
// ── 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.
|
||||
// ── HD-Grab ────────────────────────────────────────────────────────────────
|
||||
// Wenn liveSize == hiresSize: kein Format-Wechsel nötig. Live-Frame direkt
|
||||
// zurückgeben (on-demand startet den Stream bei Bedarf). Schnell, kein Gerät-
|
||||
// Neustart, kein Format-Übergangs-Problem.
|
||||
//
|
||||
// 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.
|
||||
// Wenn liveSize ≠ hiresSize: Live stoppen → hires-FFmpeg → zurück.
|
||||
// minWidth (90 % der Soll-Breite) verhindert dass Übergangs-Frames (falsche
|
||||
// Auflösung aus dem v4l2-Buffer des vorigen Formats) akzeptiert werden.
|
||||
// Beispiel: hiresSize="1280x960" → minWidth=1152 → lehnt 640er-Frames ab.
|
||||
async grabHires(opts = {}) {
|
||||
// Shortcut: keine Format-Umschaltung wenn Live- und Hires-Auflösung identisch
|
||||
if (this.liveSize === this.hiresSize) {
|
||||
return this.getFrame();
|
||||
}
|
||||
|
||||
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
|
||||
minWidth = Math.floor(hiresW * 0.9), // nur Frames nahe der Soll-Breite akzeptieren
|
||||
settleFrames = 6,
|
||||
maxWaitMs = 10000, // mehr Zeit: Kamera braucht nach Format-Wechsel länger
|
||||
maxWaitMs = 10000,
|
||||
} = opts;
|
||||
if (this.lock) throw new Error('HD-Grab läuft bereits');
|
||||
this.lock = true;
|
||||
@@ -268,7 +276,7 @@ class CameraSwitch extends EventEmitter {
|
||||
'-f', 'v4l2', '-input_format', 'mjpeg',
|
||||
'-video_size', this.hiresSize, '-framerate', String(this.hiresFps),
|
||||
'-i', this.device,
|
||||
...videoOutArgs(this.encode), '-f', 'mpjpeg', 'pipe:1',
|
||||
...videoOutArgs(this.hiresEncode), '-f', 'mpjpeg', 'pipe:1',
|
||||
];
|
||||
let p;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user