Skip to main content
Launch the native camera server binary from your app, wait for it to be ready, and shut it down cleanly on exit. The Alpha Camera REST API server is a C++ binary that must be running somewhere on the network — usually on the same machine as the camera. This recipe is for apps that want to own the server’s lifecycle.

When to use

  • Desktop apps (Electron, Tauri, PyQt, SwiftUI macOS) that should be self-contained — the user shouldn’t have to start a separate server
  • CI or test environments that need a camera server per run
  • Dev harnesses where you’re iterating on server + client together

When NOT to use

  • Anything on iOS — iOS apps can’t spawn subprocesses. Use a server running elsewhere (laptop, Raspberry Pi).
  • Browser-only UIs — point at an already-running server
  • Server is deployed separately from your app (e.g. always-on Pi)

Where does the binary come from?

The camera server binary ships with @alpha-sdk/api on npm via platform-specific optional dependencies. For self-contained apps, the easiest path:
  • Node/Electron: npm install @alpha-sdk/api — the camera-server CLI in node_modules/.bin/ is the binary launcher
  • Python: Install Node + @alpha-sdk/api, or download the binary from GitHub releases
  • Swift macOS: Ship the binary inside your .app bundle’s Resources, or download on first run
For this recipe, we assume the binary is at a path your app controls. The current macOS example app resolves it from a local npm install first (node_modules/@alpha-sdk/darwin-arm64/CameraWebApp), then falls back to CAMERA_SERVER_BINARY.

TypeScript / Node.js

Complete recipe

Usage

This is the boundary the real Next.js example app uses:
  • route owns ServerManager
  • browser code only talks to /api/server
  • the camera lifecycle layer then points @alpha-sdk/client at the returned port

Python

Complete recipe

Usage


Swift (macOS only)

iOS cannot spawn processes. This recipe applies only to macOS (#if os(macOS)).

Complete recipe

Usage


Common pitfalls

  • Handle Ctrl-C. If your app gets SIGINT, you need to call stop() — otherwise the server keeps running. Wire a signal handler or use the context-manager variants (Python async with, Swift defer).
  • Port conflicts. The real macOS app does not assume 8080 is free. It first reuses a healthy server, then reaps stale CameraWebApp orphans, then walks to the next free port.
  • Stdout buffering. Node’s spawn doesn’t buffer if you drain stdout. Python needs bufsize=1 + explicit read loop. Swift needs a readabilityHandler. Forgetting these silently stalls the server when its output buffer fills (~64KB).
  • Don’t kill the server on minor errors. Only call stop() on app exit or when you actually want it gone. Transient HTTP errors from camera commands aren’t server problems.
  • Main-actor teardown can deadlock on app quit. The real app snapshots serverURL + connectedCameraId and performs shutdown with plain URLSession off-actor so AppKit termination does not hang.

Health check before starting

If you want to avoid a port conflict, probe first:

Verified against

The Swift section mirrors example_swift_app/Sources/AlphaCameraExample/ServerManager.swift and its shutdown path in example_swift_app/Sources/AlphaCameraExample/AppCoordinator.swift.