Skip to main content

AbstractCamera

Camera control abstractions for Python and the Abstract* ecosystem: one thread-safe orchestrator (CameraManager) drives any camera family behind a session protocol — tethered PTP bodies over libgphoto2, the machine's own cameras (macOS AVFoundation), and a scriptable simulator for camera-less development and tests. A CameraHub pilots several cameras at once (one worker per camera, hardware-validated with four simultaneously), with per-device capture folders under ~/Pictures/<device>/.

What you get

  • A high-level orchestrator: CameraManager — live view (latest-JPEG + measured fps), honest config dials backed by a write-verification ledger (every write is confirmed or explicitly declared reverted), single/burst/movie capture, focus actions, an absolute-deadline intervalometer with JSONL manifests, live-view detection (lightning/meteor/motion) with auto-fire, a rolling pre-capture buffer, and automatic capture downloads.
  • Family adapters (hardware-validated): adapters/
    • Nikon Z (validated on a Z6 II): exposure-blocking triggers, lazy config settling, live-view-gated writes, movie prohibit pre-checks, wedge recovery.
    • Sony Alpha (validated on an A7R IV): async write settling with verify-retry, [-2] busy backoff, prioritymode gating, press-and-hold bursts, silent-AF-refusal detection, fetch-on-announce downloads (sdram slot eviction), honest unconfirmable-movie receipts.
    • Webcam (validated on a MacBook Pro camera): honest capability surface — one real dial (resolution), stills that are video frames and say so, genuinely confirmable in-process MP4 recording, detection and intervalometer riding the frame stream.
    • DWARF smart telescope (network/Wi-Fi, DwarfLab API v2): RTSP live view, device-table exposure/gain dials, album-backed captures that download over Wi-Fi, and the MOUNT as family actions — GOTO (RA/Dec or solar-system), joystick slews, calibration, astro autofocus.
    • Generic PTP fallback for unknown tethered bodies.
  • Multi-camera piloting: hub.py — a CameraHub runs one manager/worker per connected camera (concurrent live views, sequences and recordings), tracks an ACTIVE selection for single-panel hosts, and derives stable device identities (model slug + serial disambiguation) that name the per-device capture folders <root>/<device>/[<sequence>/] with an on-device/local save policy.
  • Transport drivers + discovery: drivers/, discovery.py — non-invasive list_cameras() across transports (no device opened, no LED, no permission prompt at list time). Webcam identity is the AVFoundation uniqueID and capture opens THAT device natively (ADR 0009: names cannot point at the wrong camera); Continuity iPhones labeled, never auto-picked.
  • A simulator that is a drop-in gphoto2 module: sim/gphoto2.py with Nikon Z6 II and Sony A7R IV personalities reproducing hardware-measured quirks (ABSTRACTCAMERA_FAKE=1).
  • Device media downloads, one abstraction across devices (ADR 0011): abstractcamera download copies ALL media a device holds into ~/Pictures/<device>/ — USB-mounted cards (auto-detected by album signature) or the DWARF album over Wi-Fi (--host); --delete frees the device after size-verified copies (protected device state like the DWARF's dark library always stays). Per-device MediaStore adapters ride one sync engine that owns all safety rules; PTP-card stores (Sony/Nikon) are the named next adapters.
  • A CLI for manual checks: abstractcamera list / abstractcamera preview / abstractcamera download (self-contained local operations). Detection runs in-process and its events are readable through the capability's event API (camera_get_events / /v1/camera/events); waking a durable workflow on motion is a consumer built at a framework entry (gateway run / flow), not a camera-shipped daemon.
  • AbstractCore integration (ADR 0012): installing abstractcamera beside AbstractCore auto-registers the camera capability (entry point abstractcore.capabilities_plugins) — open/close cameras, capture photos and bounded video clips, arm motion/lightning/meteor detection with auto-capture — plus an explicit AI tool set: from abstractcamera.integrations.abstractcore_tools import camera_tools then llm.generate("Take a photo if something moves", tools=camera_tools()). Eleven camera_* tools (including camera_preview_photo — look without firing the shutter) ship with a classification map (captures_environment is the privacy fact approval layers key on).

Install

pip install abstractcamera                 # webcam + simulator (numpy + OpenCV)
pip install "abstractcamera[gphoto2]"      # + tethered PTP bodies (libgphoto2)
pip install "abstractcamera[clips]"        # + MP4 clip/movie encoding (PyAV)
pip install "abstractcamera[raw]"          # + RAW capture thumbnails (rawpy)
pip install "abstractcamera[dwarf]"        # + DWARF smart telescopes (Wi-Fi)
pip install "abstractcamera[all]"          # everything above

Quickstart

from abstractcamera import CameraManager, list_cameras

for camera in list_cameras():
    print(camera["id"], camera["name"])

manager = CameraManager()
status = manager.connect()            # default: first PTP body, else webcam
manager.set_config_value("iso", "800")   # confirmed/reverted via the ledger
manager.request_trigger()                # capture -> auto-download + catch log
jpeg, seq = manager.get_latest_frame()   # live view
manager.start_interval_sequence(interval_s=5.0, count=10)
manager.disconnect()

Camera-less development: set ABSTRACTCAMERA_FAKE=1 and every transport is replaced by the simulator (scriptable via abstractcamera.sim.gphoto2.configure).

How it fits together

flowchart LR
  Host[Host app / CLI] --> CM[CameraManager]
  CM --> W[worker thread: one owner of all camera I/O]
  W --> AD[family adapter: Nikon Z / Sony Alpha / webcam / generic]
  AD --> S[CameraSession: gphoto2.Camera / WebcamSession / simulator]
  D[discovery + drivers] --> CM

The manager owns everything family-independent (scheduling windows, the write ledger, downloads, detection, the watchdog); the adapter owns every family quirk; the session speaks the pinned wire protocol (wire.py, values pinned to libgphoto2). Architecture decisions live in docs/adr/.

Honesty principles (ADR 0004)

Capabilities never pretend: a webcam exposes no ISO dial instead of a fake one; Sony movie recording is labeled unconfirmable over USB; every config write is confirmed against the body or explicitly reported reverted; webcam names are reported from the same device object the session captures from (ADR 0009 — positional guessing is gone).

Documentation

AbstractFramework ecosystem

AbstractCamera is part of the AbstractFramework ecosystem (https://github.com/lpalbou/AbstractFramework), alongside AbstractCore, AbstractVision, AbstractVoice, and friends. It was extracted from the BlackPixel desktop editor's hardware-validated tethering stack (2026-07-12) through a 3-agent adversarial design review.

License

MIT — see LICENSE.

Metadata

Release files for abstractcamera 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for abstractcamera 0.2.1
File Size Uploaded
abstractcamera-0.2.1.tar.gz 361.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for abstractcamera 0.2.1
File Interpreter ABI Platform
abstractcamera-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 555.0 kB

Release files / abstractcamera-0.2.1.tar.gz

Download URL abstractcamera-0.2.1.tar.gz
Size 361.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e14d1a0a5d679622560c2bc05de677a28ddf5939868c5079f79b03ac45b9b3cc
BLAKE2b-256 checksum
How to use checksums
8b07c8f5e6b223ec613672781488bd526015c437ea5ed6c1cb4d5362ab1881b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / abstractcamera-0.2.1-py3-none-any.whl

Download URL abstractcamera-0.2.1-py3-none-any.whl
Size 194.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e1f1c973b09d835456d7debab430b42f21daa206f29dbfeec50c7b18b8766f8d
BLAKE2b-256 checksum
How to use checksums
7a785d43205a78cd0f93090340dd35fa631b9c97608d736a1baf6ef239ca17bc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page