A lightweight, pure TypeScript camera component with canvas rendering and photo capture capabilities.
npm install auto-cameraA lightweight, pure TypeScript camera component with canvas rendering and photo capture capabilities.
- Canvas-based video rendering with responsive sizing
- Photo capture with JPEG quality control
- Front/back camera switching
- Event-driven architecture
- Optional UI controls
- No external dependencies
``bash`
npm install auto-camera
`ts
import { createCamera } from "auto-camera";
// Create camera with controls
const { camera, controls, destroy } = createCamera("#camera-container", {
camera: {
facingMode: "user",
mirrored: true,
},
controls: true,
});
// Capture a photo
const result = await camera.capture();
console.log(result.dataUrl);
// Clean up when done
destroy();
`
For more control, use the AutoCamera class directly:
`ts
import { AutoCamera, CameraControls } from "auto-camera";
const camera = new AutoCamera({
target: "#camera-container",
facingMode: "environment",
width: 1920,
height: 1080,
aspectRatio: 16 / 9,
jpegQuality: 0.92,
mirrored: false,
autoStart: true,
});
// Optionally add UI controls
const controls = new CameraControls(camera, {
position: "bottom",
showCaptureButton: true,
showSwitchButton: true,
});
controls.mount(camera.getCanvas().parentElement);
`
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| target | HTMLElement \| string | required | Target element or selector |facingMode
| | "user" \| "environment" | "environment" | Camera facing mode |width
| | number | 1280 | Preferred video width |height
| | number | 720 | Preferred video height |aspectRatio
| | number | 16/9 | Aspect ratio for canvas |jpegQuality
| | number | 0.92 | JPEG quality (0-1) |mirrored
| | boolean | false | Mirror the video horizontally |autoStart
| | boolean | true | Auto-start camera on mount |
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| showCaptureButton | boolean | true | Show capture button |showSwitchButton
| | boolean | true | Show camera switch button |captureButtonContent
| | string | "📷" | Capture button content |switchButtonContent
| | string | "🔄" | Switch button content |position
| | "bottom" \| "top" \| "left" \| "right" | "bottom" | Controls position |className
| | string | "" | Custom CSS class |
| Method | Returns | Description |
|--------|---------|-------------|
| start() | Promise | Start the camera stream |stop()
| | void | Stop the camera stream |pause()
| | void | Pause the stream |resume()
| | void | Resume from pause |capture()
| | Promise | Capture current frame |captureAndDownload(filename?)
| | Promise | Capture and download as JPG |switchCamera()
| | Promise | Toggle front/back camera |getState()
| | CameraState | Get current state |getCanvas()
| | HTMLCanvasElement | Get canvas element |getStream()
| | MediaStream | Get media stream |destroy()
| | void | Clean up resources |
Subscribe to events using on() or once():
`ts
// Subscribe to an event
camera.on("capture", (result) => {
console.log("Photo captured:", result.width, "x", result.height);
});
camera.on("error", (error) => {
console.error(error.code, error.message);
});
// Subscribe once (auto-unsubscribes after first emit)
camera.once("ready", () => {
console.log("Camera is ready!");
});
// Unsubscribe using the returned function
const unsubscribe = camera.on("start", () => console.log("Started"));
unsubscribe(); // removes the listener
// Or use off() with a named function
function onStateChange(state) {
console.log("State:", state);
}
camera.on("stateChange", onStateChange);
camera.off("stateChange", onStateChange); // removes the listener
`
| Event | Payload | Description |
|-------|---------|-------------|
| ready | - | Camera initialized |start
| | - | Stream started |stop
| | - | Stream stopped |pause
| | - | Stream paused |resume
| | - | Stream resumed |capture
| | CaptureResult | Photo captured |error
| | CameraError | Error occurred |stateChange
| | CameraState | State changed |destroy
| | - | Camera destroyed |
`ts`
interface CaptureResult {
dataUrl: string; // Base64 data URL
blob: Blob; // Image blob
width: number; // Image width
height: number; // Image height
timestamp: number; // Capture timestamp
}
`ts`
interface CameraError {
code: "NOT_ALLOWED" | "NOT_FOUND" | "NOT_READABLE" | "OVERCONSTRAINED" | "UNKNOWN";
message: string;
originalError?: Error;
}
#### Error Codes
| Code | Cause | Typical Resolution |
|------|-------|-------------------|
| NOT_ALLOWED | User denied camera permission, or page is not served over HTTPS | Prompt user to grant permission in browser settings, or serve page over HTTPS |NOT_FOUND
| | No camera device available on the system | Inform user that a camera is required |NOT_READABLE
| | Camera is already in use by another application or browser tab | Ask user to close other apps using the camera |OVERCONSTRAINED
| | Requested resolution or facing mode not supported by the camera | Use lower resolution or remove facingMode constraint |UNKNOWN
| | Unexpected error not matching known categories | Check originalError for details, display generic error message |
The camera transitions through these states:
- idle - Initial state, not streaminginitializing
- - Requesting camera accessstreaming
- - Actively streaming videopaused
- - Stream pausederror
- - An error occurreddestroyed
- - Component destroyed
Requires browsers with MediaDevices.getUserMedia()` support (all modern browsers).
MIT