Browser vs server implementations and how they map to real frameworks
The Client SDK ships two CameraManager implementations. Both share the same camera control API (manager.client), but differ in how they connect to the native server binary.
Import:camera-remote-web-api/serverManages the native binary process and camera lifecycle. start() is async — it boots the binary, waits for HTTP readiness, then begins polling and SSE.
Copy
import { CameraManager } from 'camera-remote-web-api/server';const manager = new CameraManager({ port: 8080 });await manager.start(); // Async — spawns binary, waits for ready
Server-only methods:getPort(), isRunning(), getPid(), getStdout(), getStderr()Use case: Node.js backends, API routes, CLI tools, Electron main process.
Import:camera-remote-web-apiConnects to an already-running server via baseUrl. start() is synchronous — it immediately begins polling and SSE against the given URL. No binary management.
Copy
import { CameraManager } from 'camera-remote-web-api';const manager = new CameraManager({ baseUrl: 'http://localhost:8080',});manager.start(); // Synchronous — begins polling + SSE
Use case: React components, vanilla JS, Electron renderer, any browser context.
Use both variants: server in the backend, browser in the frontend.
Copy
import { CameraManager } from 'camera-remote-web-api/server';let manager: CameraManager | null = null;export async function POST() { if (!manager) { manager = new CameraManager({ port: 8080, autoPort: true, binaryPath: '/path/to/CameraWebApp', }); await manager.start(); } return Response.json({ port: manager.getPort() });}
Next.js bundler strips native createRequire — always pass an explicit binaryPath in API routes.
Copy
import { CameraManager } from 'camera-remote-web-api/server';const manager = new CameraManager({ port: 8080 });await manager.start();// Expose port to renderer via IPCipcMain.handle('get-port', () => manager.getPort());