Multi-Camera Control & Selective Operations
Discover cameras, get the full list, and trigger operations on selected cameras.Copy
import { CameraManager } from 'camera-remote-web-api/server';
const manager = new CameraManager({
autoConnect: false,
connectionMode: 'remote-transfer',
});
await manager.start();
// Wait for cameras to be discovered
await new Promise(resolve => setTimeout(resolve, 3000));
// Get full list of discovered cameras
const cameras = manager.getCameras();
console.log(`Found ${cameras.length} camera(s):`);
cameras.forEach(c => console.log(` ${c.info.model} (${c.info.id}) via ${c.info.connectionType}`));
// Connect to a specific camera by ID
const target = cameras[0];
if (target) {
await manager.connect(target.info.id, { mode: 'remote-transfer' });
}
manager.on('camera-ready', async ({ cameraId }) => {
await manager.client.setPriorityKey(cameraId, { setting: 'pc-remote' });
});
// Trigger all connected cameras simultaneously
async function triggerAll() {
const connected = manager.getCameras().filter(c => c.state === 'connected');
console.log(`Triggering ${connected.length} cameras...`);
await Promise.all(
connected.map(c => manager.client.triggerShutter(c.info.id))
);
}
File Transfer Operations
SD card download
An SD card must be inserted in the camera for file transfer and contents operations.
Copy
import { CameraManager } from 'camera-remote-web-api/server';
import { EventStream } from 'camera-remote-web-api';
const manager = new CameraManager({
connectionMode: 'remote-transfer',
});
manager.on('camera-ready', async ({ cameraId }) => {
const client = manager.client;
// Listen for completed downloads
const events = new EventStream(`http://localhost:${manager.getPort()}`, cameraId);
events.on('downloadComplete', (data) => {
console.log(`Saved: ${data.filename}`);
});
events.on('transferProgress', (data) => {
console.log(`Transfer: ${data.percent}%`);
});
// List and download files from slot 1
const { files } = await client.listSDCardFiles(cameraId, 1);
console.log(`Found ${files.length} files`);
for (const file of files) {
await client.downloadSDCardFile(cameraId, 1, file.content_id, file.file_id);
}
});
await manager.start();
Auto-save to host PC
still-image-store-destination and auto-save only work in remote connection mode. They are not available in remote-transfer or contents modes.remote mode, configure the camera to automatically save photos to the host:
Copy
const manager = new CameraManager({
connectionMode: 'remote',
});
manager.on('camera-ready', async ({ cameraId }) => {
const client = manager.client;
await client.setPriorityKey(cameraId, { setting: 'pc-remote' });
// Set save destination to both camera + host PC
await client.setProperty(cameraId, 'still-image-store-destination', { value: '0x3' });
// Configure where the server saves files
await client.setSaveInfo(cameraId, { path: '/tmp/photos', prefix: 'IMG_', startNo: 1 });
// Listen for auto-transferred files
const events = new EventStream(`http://localhost:${manager.getPort()}`, cameraId);
events.on('downloadComplete', (data) => {
console.log(`Auto-saved: ${data.filename}`);
});
// Shoot — file auto-transfers to /tmp/photos
await client.afShutter(cameraId);
});
await manager.start();
Live View Display & OSD
Stream live view frames and control on-screen display overlay.Copy
import { CameraManager } from 'camera-remote-web-api/server';
import { LiveViewStream } from 'camera-remote-web-api/server';
const manager = new CameraManager({
connectionMode: 'remote-transfer',
});
manager.on('camera-ready', async ({ cameraId }) => {
const client = manager.client;
await client.setPriorityKey(cameraId, { setting: 'pc-remote' });
// Enable live view with OSD overlay (exposure info, focus area)
await client.enableLiveView(cameraId, { osd: true });
await client.startLiveViewStream(cameraId);
// HTTP polling (~15fps)
const poll = setInterval(async () => {
const frame = await client.getLiveViewFrame(cameraId);
process.stdout.write(`Frame: ${frame.byteLength} bytes\r`);
}, 66);
// OR: WebSocket streaming (~15fps)
const liveView = new LiveViewStream(`ws://localhost:${manager.getPort()}`, cameraId);
liveView.onFrame((jpeg: ArrayBuffer) => {
// Each message is a complete JPEG frame
process.stdout.write(`WS Frame: ${jpeg.byteLength} bytes\r`);
});
// Clean up
// clearInterval(poll);
// liveView.close();
// await client.stopLiveViewStream(cameraId);
});
await manager.start();
Camera Settings Backup & Restore
Save and restore complete camera configurations using.DAT settings files.
Settings file operations are not supported on all cameras. The following models do not support settings download/upload: ILCE-9M2, ILCE-7RM4, ILCE-7RM4A, ILCE-7C, DSC-RX0M2. See Compatibility for details.
Copy
import { CameraManager } from 'camera-remote-web-api/server';
const manager = new CameraManager({
connectionMode: 'remote',
});
manager.on('camera-ready', async ({ cameraId }) => {
const client = manager.client;
// List available settings files on camera
const { files } = await client.listSettingsFiles(cameraId);
console.log('Settings files:', files);
// Download a settings .DAT file to host PC
await client.downloadCameraSettings(cameraId, { filename: 'CUMSET.DAT' });
console.log('Settings downloaded to host PC');
// Upload a settings .DAT file back to camera
await client.uploadCameraSettings(cameraId, { filename: 'CUMSET.DAT' });
console.log('Settings uploaded to camera');
});
await manager.start();
Continuous Shooting Burst
Configure drive mode for continuous shooting and trigger a burst.Copy
import { CameraManager } from 'camera-remote-web-api/server';
const manager = new CameraManager({
connectionMode: 'remote-transfer',
});
manager.on('camera-ready', async ({ cameraId }) => {
const client = manager.client;
await client.setPriorityKey(cameraId, { setting: 'pc-remote' });
// Configure shooting settings
await client.setProperty(cameraId, 'iso', { value: '400' });
await client.setProperty(cameraId, 'aperture', { value: 'f/2.8' });
await client.setProperty(cameraId, 'shutter-speed', { value: '1/250' });
await client.setProperty(cameraId, 'drive-mode', { value: 'continuous-hi' });
// Verify settings were applied
const iso = await client.getProperty(cameraId, 'iso');
console.log('ISO set to:', iso.data.formatted);
// Start continuous shooting burst (hold shutter for 3 seconds)
await client.triggerShutter(cameraId, { action: 'down' });
setTimeout(async () => {
await client.triggerShutter(cameraId, { action: 'up' });
console.log('Burst complete');
}, 3000);
});
await manager.start();

