# @elizaos/capacitor-camera Capacitor plugin for camera preview, photo capture, and video recording. Works across web (via the `MediaDevices` API), iOS (via AVFoundation), and Android (via Camera2). ## What it does - **Live preview** — stream a camera feed into any DOM element with configurable resolution, frame rate, and mirror mode. - **Photo capture** — snapshot a JPEG, PNG, or WebP image as base64 from the active preview, with optional resize and quality control. - **Video recording** — record video with optional audio, configurable bitrate, and automatic stop on max duration or file size. - **Camera control** — zoom, focus point, exposure point, flash/torch mode, white balance. - **Device enumeration** — list available cameras with capabilities (direction, zoom range, resolutions, frame rates). - **Permissions** — check and request camera + microphone permissions. - **Events** — subscribe to `frame`, `error`, and `recordingState` events. ## Installation This is a Capacitor plugin. Add it to a Capacitor project: ```bash npm install @elizaos/capacitor-camera npx cap sync ``` ### iOS The plugin uses `AVFoundation`, `Photos`, and `UIKit`. Add the following keys to `Info.plist`: ```xml NSCameraUsageDescription Camera access is required for photo and video capture. NSMicrophoneUsageDescription Microphone access is required for video recording with audio. NSPhotoLibraryAddUsageDescription Photo library access is required to save captured media. ``` Minimum deployment target: iOS 15.0. ### Android Add the following permissions to `AndroidManifest.xml`: ```xml ``` ## Usage ```typescript import { Camera } from "@elizaos/capacitor-camera"; // Check and request permissions const status = await Camera.checkPermissions(); if (status.camera !== "granted") { await Camera.requestPermissions(); } // List available cameras const { devices } = await Camera.getDevices(); // Start a preview in a DOM element const container = document.getElementById("camera-container"); const result = await Camera.startPreview({ element: container, direction: "back", resolution: { width: 1920, height: 1080 }, frameRate: 30, }); // Capture a photo const photo = await Camera.capturePhoto({ quality: 90, format: "jpeg" }); // photo.base64 contains the image data // Record video await Camera.startRecording({ audio: true, quality: "high", maxDuration: 60 }); // ... later ... const video = await Camera.stopRecording(); // video.path is a blob: URL on web, or a file path on native // Stop preview and release camera await Camera.stopPreview(); ``` ### Camera settings ```typescript // Zoom (1.0 = no zoom) await Camera.setZoom({ zoom: 2.0 }); // Manual focus / exposure (normalized 0–1 coordinates) await Camera.setFocusPoint({ x: 0.5, y: 0.5 }); await Camera.setExposurePoint({ x: 0.5, y: 0.5 }); // Batch settings update await Camera.setSettings({ settings: { flash: "auto", whiteBalance: "daylight", focusMode: "continuous", }, }); ``` ### Events ```typescript const frameHandle = await Camera.addListener("frame", (event) => { console.log(event.timestamp, event.width, event.height); }); const stateHandle = await Camera.addListener("recordingState", (state) => { console.log(state.isRecording, state.duration, state.fileSize); }); // Clean up await Camera.removeAllListeners(); ``` ## API Full TypeScript definitions are in `src/definitions.ts`. Key types: | Type | Description | |---|---| | `CameraDevice` | Device info: id, label, direction, capabilities | | `CameraPreviewOptions` | Options for `startPreview` | | `PhotoCaptureOptions` | Options for `capturePhoto` (quality, format, size, gallery save) | | `PhotoResult` | base64 image, format, dimensions, optional EXIF | | `VideoCaptureOptions` | Options for `startRecording` (quality, duration, size, audio, bitrate) | | `VideoResult` | Path (blob URL or file path), duration, dimensions, file size, mime type | | `CameraSettings` | flash, zoom, focusMode, exposureMode, exposureCompensation, whiteBalance | | `CameraPermissionStatus` | camera / microphone: `"granted"` \| `"denied"` \| `"prompt"`; photos additionally allows `"limited"` | ## Platform notes - **Web:** Flash/torch is not controllable via the `MediaDevices` API on most desktop browsers. Manual focus and exposure require the browser/device to report `"manual"` capability. Video is recorded as a `blob:` URL using `MediaRecorder`; preferred codec order is `vp9+opus` → `vp8+opus` → `webm` → `mp4`. - **iOS:** AVFoundation-backed. Requires iOS 15.0+, Swift 5.9. - **Android:** Camera2 API-backed. - **Node (Electrobun desktop):** Supported via Electrobun native modules.