Skip to main content

Multi-Camera Control & Selective Operations

Discover cameras, get the full list, and trigger operations on selected cameras.
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.
List and download files from the camera’s SD card:
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.
In remote mode, configure the camera to automatically save photos to the host:
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.
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.
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();
See Camera Settings HTTP API for full endpoint documentation.

Continuous Shooting Burst

Configure drive mode for continuous shooting and trigger a burst.
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();