@@ -0,0 +1,61 @@
|
||||
import { spawn } from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
|
||||
export class PortalCamera {
|
||||
constructor({
|
||||
helper = path.resolve(new URL('./py/portal_camera.py', import.meta.url).pathname),
|
||||
python = 'python3',
|
||||
spawnImpl = spawn,
|
||||
tmpDir = '/tmp/jarvis-webcam',
|
||||
timeoutMs = 8000,
|
||||
accessTimeoutMs = 120_000,
|
||||
} = {}) {
|
||||
this.helper = helper;
|
||||
this.python = python;
|
||||
this.spawnImpl = spawnImpl;
|
||||
this.tmpDir = tmpDir;
|
||||
this.timeoutMs = timeoutMs;
|
||||
this.accessTimeoutMs = accessTimeoutMs;
|
||||
}
|
||||
|
||||
access({ device = '' } = {}) {
|
||||
return this._run(['access'], this.accessTimeoutMs, device);
|
||||
}
|
||||
|
||||
capture(output, { device = '' } = {}) {
|
||||
return this._run(['capture', output], this.timeoutMs, device);
|
||||
}
|
||||
|
||||
_run(args, timeoutMs, device) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = this.spawnImpl(this.python, [this.helper, ...args], {
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
env: { ...process.env, JARVIS_WEBCAM_DEVICE: device || '' },
|
||||
});
|
||||
let out = '';
|
||||
let err = '';
|
||||
let settled = false;
|
||||
const timer = setTimeout(() => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
child.kill('SIGTERM');
|
||||
reject(new Error('webcam helper timed out'));
|
||||
}, timeoutMs);
|
||||
const done = (fn) => (value) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
fn(value);
|
||||
};
|
||||
child.stdout.on('data', (chunk) => { out += chunk; });
|
||||
child.stderr.on('data', (chunk) => { err += chunk; });
|
||||
child.on('error', done(reject));
|
||||
child.on('close', (code) => {
|
||||
let payload = {};
|
||||
try { payload = JSON.parse(String(out).trim().split('\n').pop() || '{}'); } catch {}
|
||||
if (code === 0 && payload.ok) done(resolve)(payload);
|
||||
else done(reject)(new Error(payload.error || err.trim() || `webcam helper exited ${code}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user