capture_helper.api module

Capture Helper — FastAPI HTTP surface.

Exposes every public function in capture_helper as an HTTP endpoint so capture-helper can be dropped behind any reverse proxy and consumed by other services. Kept intentionally minimal:

  • Query / form parameters for device selection.

  • JSONResponse for device enumeration / picking / input-args (small structured payloads).

  • StreamingResponse (ZIP) for camera snapshots — one download per call with the raw .bgr24 frames inside.

  • FileResponse for the WAV output from /capture/mic.

  • BackgroundTasks cleans temp files after the response has been streamed — no leftover garbage on disk.

Install the extra to get the runtime dependencies:

pip install 'capture-helper[api]'

Then run the app with any ASGI server:

uvicorn capture_helper.api:app --host 0.0.0.0 --port 8000

Usage Example

>>> # Start the server:
>>> #   uvicorn capture_helper.api:app --reload
>>> # List devices:
>>> #   curl http://localhost:8000/sources
>>> # Pick a camera by name:
>>> #   curl 'http://localhost:8000/pick?kind=camera&name=FaceTime'
>>> # Grab 10 frames at 320x240 into a ZIP:
>>> #   curl -o frames.zip \
>>> #     'http://localhost:8000/capture/camera?output_width=320&output_height=240&max_frames=10'
>>> # Record 3s of mic PCM to a WAV:
>>> #   curl -o mic.wav 'http://localhost:8000/capture/mic?seconds=3'
>>> # Full OpenAPI docs at http://localhost:8000/docs

Author

Warith Harchaoui, Ph.D. — https://linkedin.com/in/warith-harchaoui/

capture_helper.api.capture_camera(background, name=fastapi.Query, index=fastapi.Query, width=fastapi.Query, height=fastapi.Query, fps=fastapi.Query, output_width=fastapi.Query, output_height=fastapi.Query, pad_color=fastapi.Query, max_frames=fastapi.Query)

Grab max_frames frames from the selected camera. Response is a ZIP.

Parameters:
  • background (fastapi.BackgroundTasks)

  • name (str | None)

  • index (int | None)

  • width (int | None)

  • height (int | None)

  • fps (float | None)

  • output_width (int | None)

  • output_height (int | None)

  • pad_color (str)

  • max_frames (int)

capture_helper.api.capture_mic(background, name=fastapi.Query, index=fastapi.Query, seconds=fastapi.Query, sample_rate=fastapi.Query, frame_ms=fastapi.Query, mono=fastapi.Query)

Record seconds s of PCM from the selected microphone into a WAV file.

Parameters:
  • background (fastapi.BackgroundTasks)

  • name (str | None)

  • index (int | None)

  • seconds (float)

  • sample_rate (int)

  • frame_ms (int)

  • mono (bool)

capture_helper.api.gui()

Serve the self-contained single-page scene-configurator GUI.

The page (defined in capture_helper.gui) is a build-step-free HTML + Tailwind-CDN + vanilla-JS client that calls the very same /sources / /preview/... / /scene/... endpoints defined here. It adds no server-side logic — it is purely a friendlier front door to the API.

Returns:

The complete HTML document (status 200, text/html).

Return type:

HTMLResponse

capture_helper.api.health()

Simple liveness probe — no dependency check, just proves the app is up.

Return type:

dict

capture_helper.api.input_args(kind=fastapi.Query, name=fastapi.Query, index=fastapi.Query)

Print the ffmpeg -f DRIVER -i SPEC argv fragment for a resolved device.

Parameters:
  • kind (str)

  • name (str | None)

  • index (int | None)

Return type:

fastapi.responses.JSONResponse

capture_helper.api.pick(kind=fastapi.Query, name=fastapi.Query, index=fastapi.Query)

Resolve a single capture device by kind / name / index.

Parameters:
  • kind (str)

  • name (str | None)

  • index (int | None)

Return type:

fastapi.responses.JSONResponse

capture_helper.api.preview_camera_jpg(name=fastapi.Query, index=fastapi.Query, output_width=fastapi.Query, output_height=fastapi.Query)

Return a single live JPEG snapshot from the selected camera.

Parameters:
Returns:

A image/jpeg body (200), or HTTP 404 when no matching camera exists, or HTTP 503 when a frame cannot be captured (permission / busy device).

Return type:

Response

capture_helper.api.preview_camera_mjpeg(name=fastapi.Query, index=fastapi.Query, output_width=fastapi.Query, output_height=fastapi.Query, fps=fastapi.Query, max_frames=fastapi.Query)

Stream the selected camera as multipart/x-mixed-replace MJPEG.

The browser renders this directly in an <img> tag, giving a live preview tile with no client-side decoding. The stream ends when the client disconnects (or after max_frames if given).

Parameters:
  • name (optional) – Device selectors forwarded to capture_helper.pick_source().

  • index (optional) – Device selectors forwarded to capture_helper.pick_source().

  • output_width (int) – Per-frame preview size.

  • output_height (int) – Per-frame preview size.

  • fps (float) – Preview frame rate (kept low by default to stay cheap).

  • max_frames (int, optional) – Bound the stream length.

Returns:

A multipart/x-mixed-replace body, or HTTP 404 when no camera matches.

Return type:

StreamingResponse

capture_helper.api.preview_mic_level(name=fastapi.Query, index=fastapi.Query, sample_rate=fastapi.Query, window_ms=fastapi.Query)

Capture a short slice of live audio and return its level (for a VU meter).

Parameters:
Returns:

{"rms", "rms_dbfs", "peak", "peak_dbfs"}, or HTTP 404 when no matching microphone exists.

Return type:

JSONResponse

capture_helper.api.root()

Redirect the bare root to the GUI so opening the server just works.

Returns:

A 307 redirect to /gui. A human hitting http://host:port/ almost always wants the scene configurator, not a 404; machines call the documented endpoints directly, so this is safe.

Return type:

RedirectResponse

capture_helper.api.scene_auto()

Return a starter scene auto-populated from this host’s live devices.

Returns:

A valid scene (first camera full-canvas + first microphone, if any). Empty of sources on a headless host with no devices.

Return type:

JSONResponse

async capture_helper.api.scene_load(file=fastapi.File)

Validate an uploaded scene file and echo it back as JSON.

Lets the GUI round-trip a scene through the server’s own validator (so a hand-edited file is rejected with a clear message before the front-end adopts it).

Parameters:

file (UploadFile) – The uploaded .scene.json file.

Returns:

The validated scene, or HTTP 400 when the file is not a valid scene.

Return type:

JSONResponse

async capture_helper.api.scene_save(background, request)

Validate a posted scene and return it as a downloadable JSON artifact.

The request body is the scene JSON (as produced by the GUI). It is validated server-side (the same validation the CLI uses) and written to a temp file, then streamed back as a .scene.json download.

Parameters:
  • background (BackgroundTasks) – Used to clean the temp file after the response is sent.

  • request (Request) – Carries the raw scene JSON body.

Returns:

The validated scene as a downloadable file, or HTTP 400 on a bad scene.

Return type:

FileResponse

capture_helper.api.sources(kind=fastapi.Query)

Enumerate available capture devices as JSON.

Parameters:

kind (str | None)

Return type:

fastapi.responses.JSONResponse