Thanks to visit codestin.com
Credit goes to github.com

Skip to content

darkgrade/darkgrade

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

51 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

darkgrade

Connect to & control your camera with TypeScript

Note: Link is in alpha and APIs may change without backwards compatibility.

This library is a comprehensive TypeScript implementation of ISO-15740:2013 which most camera manufacturers from the last 2 decades have used under the hood to accept commands and transmit information. It also contains a partial implementation of various vendor specifications. libgphoto2 and its command line tool gphoto2 also use these libraries under the hood.

npm version Bundle Size TypeScript Dependencies

✨ Highlights

  • πŸš€ Zero Configuration - Automatic camera detection and vendor-specific features
  • πŸ“¦ 55kB Bundled - Lightweight and tree-shakable
  • πŸ”₯ 1 major dependency - just usb for Node.js
  • 🌐 Runs anywhere - Works in both browser & Node.js
  • 🎯 Pure TypeScript - Full type safety and modern DX
  • ✨ Simple API - Connect and control your camera with minimal code
  • πŸ“· Vendor Extensions - Extended features for Sony, Nikon & Canon
    • Sony ⍺ Series - Live view, video recording, SDIO operations
    • Nikon Z Series - Live view, extended properties
    • Canon EOS R Series - Remote control, event polling

πŸš€ Quick Start

Installation

npm install @darkgrade/link

Basic Usage

import { Camera } from '@darkgrade/link'

const camera = new Camera()
await camera.connect()

// Control camera settings
await camera.setIso('800')
await camera.setShutterSpeed('1/250')
await camera.setAperture('f/2.8')

// Capture an image
const { data } = await camera.captureImage()

await camera.disconnect()

πŸ“– Usage Examples

Camera Settings

// Get current settings
const currentIso = await camera.getIso()
const currentShutter = await camera.getShutterSpeed()
const currentAperture = await camera.getAperture()

// Set new values
await camera.setIso('1600')
await camera.setShutterSpeed('1/500')
await camera.setAperture('f/4.0')

Event Handling

import { Camera } from '@darkgrade/link'

const camera = new Camera()
await camera.connect()

// Listen for camera events
camera.on(camera.getInstance().registry.events.ObjectAdded, event => {
    console.log('New object added:', event.ObjectHandle)
})

camera.on(camera.getInstance().registry.events.PropertyChanged, event => {
    console.log('Property changed:', event.PropertyName)
})

// Remove event listeners
camera.off(camera.getInstance().registry.events.ObjectAdded)

Live View

// Capture live view frame (Sony & Nikon only)
const { data: liveViewFrame } = await camera.captureLiveView()

// Save or display the frame
fs.writeFileSync('liveview.jpg', liveViewFrame)

Video Recording

// Start recording (Sony & Canon only)
await camera.startRecording()

// ... record for some duration ...

// Stop recording
await camera.stopRecording()

File Management

// List all objects on camera
const objects = await camera.listObjects()

for (const [storageId, storage] of Object.entries(objects)) {
    console.log(`Storage ${storageId}: ${storage.info.storageDescription}`)

    for (const [handle, info] of Object.entries(storage.objects)) {
        console.log(`  - ${info.filename} (${info.objectCompressedSize} bytes)`)

        // Download a specific object
        const fileData = await camera.getObject(Number(handle), info.objectCompressedSize)
        fs.writeFileSync(info.filename, fileData)
    }
}

Advanced Property Access

// Access vendor-specific properties directly
const registry = camera.getInstance().registry

// Get property descriptor
const propValue = await camera.get(registry.properties.ExposureIndex)

// Set property with type safety
await camera.set(registry.properties.ExposureIndex, '3200')

How It Works

The Camera class automatically detects your connected camera's brand and uses the appropriate vendor-specific implementation:

  • Sony Ξ± Series β†’ Automatically uses SonyCamera with Sony extensions
  • Nikon Z Series β†’ Automatically uses NikonCamera with Nikon extensions
  • Canon EOS R Series β†’ Automatically uses CanonCamera with Canon extensions
  • Other PTP Cameras β†’ Falls back to GenericCamera with standard PTP operations

You can also import and use vendor-specific camera classes directly:

import { SonyCamera } from '@darkgrade/link'
// or NikonCamera, CanonCamera, GenericCamera

Or specify a device descriptor when initializing the Camera constructor:

import { Camera, VendorIDs } from '@darkgrade/link'

// Specify a camera brand for vendor-specific features
const camera = new Camera({
    device: {
        usb: {
            filters: [{ vendorId: VendorIDs.SONY }], // VendorIDs.NIKON, VendorIDs.CANON
        },
    },
    logger: {
        expanded: true, // Show detailed logging
    },
})

await camera.connect()

πŸ“Š Feature Compatibility

Feature Generic PTP Sony Nikon Canon
Connection βœ… βœ… βœ… βœ…
Get/Set Properties βœ… βœ… βœ… βœ…
Event Handling βœ… βœ… βœ… βœ…
Aperture Control βœ… βœ… βœ… βœ…
Shutter Speed Control βœ… βœ… βœ… βœ…
ISO Control βœ… βœ… βœ… βœ…
Capture Image βœ… βœ… βœ… βœ…
List Objects βœ… βœ… βœ… 🟑
Download Objects βœ… βœ… βœ… 🟑
Live View ❌ 1 βœ… βœ… 🟑
Video Recording ❌ 2 βœ… βœ… 3 🟑
Tested with: Ξ±6700
Ξ±7 IV
Ξ±7 V
Z6 III EOS R6 Mk.III

Notes

  1. The earliest versions of PTP date back to 2002 and this was not included in the specification (perhaps not thought of as necessary/useful/possible on the first wave of digital still cameras).
  2. Same as (1) above
  3. Nikon cameras differentiate between "photo mode" and "video mode" with an on-camera hardware switch and do not typically allow capture of (a) videos while in photo mode or (b) photos while in video mode. There are two workarounds we support:
    • You accept this limitation and get full feature support for photo OR video, but not both at the same time, via the hardware switch. This is optimal if you don't plan to do hybrid shooting within the same session.
    • We allow you to do both at the same time in either switch mode, however when you are capturing in the "wrong" mode" (e.g. you start recording a video while in photo mode), the on-screen display on your camera will be blank and say "Connected to Computer."

πŸ“š Reference

ISO 15740:2013 - PTP specification


made with ❀️ by darkgrade