Giter Club home page Giter Club logo

tethr's Introduction



Tethr

Demo

Tethr is a JavaScript/TypeScript library for controlling USB-connected digital cameras from browsers.

It is built on the top of WebUSB API and aims to support cameras from various vendors. There is a protocol called PTP (Picture Transfer Protocol), which provides a way to access cameras' functionalities such as shutter, aperture, ISO and so on via USB or TCP/IP. However, most of cameras adopt their own vendor extensions to communitate with PC and there's hardly any compatability between them. Tethr also aims to fill the gap and provide an uniform and modern interface for developers without worrying about the difference. The project is deeply inspired by libgphoto2.

Installation on Your Package

npm install https://github.com/baku89/tethr
yarn add https://github.com/baku89/tethr

Supported Cameras

As mentioned above, most vendors add their own extension to PTP. Thus it requires vendor-specific support to fully access all of each camera model's features, otherwise the library can access limited number of configurations exposed as a standard device prop defined in PTP specification. The library also supports web camera fallback in the case WebUSB is disabled or no camera is connected such as smartphone.

Here's the list of camera models

Vendor Camera Features
Panasonic Lumix S5 Shutter, LV, AF, MF, Config
Sigma fp Shutter, LV, AF, Config
Ricoh Theta S Shutter, Config
WebCam Shutter, LV, Config

** LV: Liveview, AF: Auto Focus, MF: Manual Focus

Sample Code

This project is on very early stage of development and not yet documented. Here is the sample code for you to grasp how to use the library. Note that all of camera operations have done asyncronically and Tethr's instance methods return Promise.

import {detectTethr} from 'tethr'

const cameras = await detectTethr()

const cam = cameras[0]

await cam.init()

await cam.get('model') // 'Lumix S5'
await cam.getModel()

await cam.set('shutterSpeed', '1/1000')
await cam.setShutterSpeed('1/1000')

const exposureModeDesc = await cam.getDesc('exposureMode')
console.log(exposureModeDesc)
/* -> {
	value: 'M',
	writable: false // Because this can be set by physical dial on a camera
	option: {
		type: 'enum',
		values: ['M', 'S', 'A', 'P']
	}
} */

const autoFocusResult = await cam.runAutoFocus()

if (!autoFocusResult.status !== 'ok') {
	console.warn('AF failed')
}

const takePhotoResult = await cam.takePhoto({download: true})

if (takePhotoResult.status === 'ok') {
	const url = URL.createURLObject(takePhotoResult.value[0])
	$img.src = url
}

// Get storage informations
const storages = await cam.getStorages()

for (const storage of storages) {
	console.log('Storage ID: ' + storage.id)
	console.log('name=' + storage.name)
	console.log('free space in images=' + storage.freeSpaceInImages)
}

await cam.close()

Configs

This is a list of ConfigName and its value type:

ConfigName Type Example
aperture Apertue 2.2, 5.6, 'auto'
batteryLevel BatteryLevel 50, 100, 'ac', 'low' (Represented in range 0-100)
burstInterval number
burstNumber number
canRunAutoFocus boolean
canRunManualFocus boolean
canStartLiveview boolean
canTakePicture boolean
captureDelay number
colorMode string V-Log, Teal and Orange, CineV... (vendor-specific)
colorTemperature number 2600, 5500
contrast number
dateTime Date
destinationToSave string 'camera', 'pc', 'camera,pc'
digitalZoom number
driveMode DriveMode 'normal', 'burst', 'interval'
exposureComp string '-1 1/3' '-1/2', '0', '+2 1/3'
exposureMeteringMode ExposureMeteringMode 'average', 'multi-spot', 'center-spot'...
exposureMode ExposureMode 'P', 'A', 'S', 'M'
facingMode string 'user', 'environemnt'... (Webcam fallback only)
flashMode FlashMode 'auto', 'off', 'fill'...
focalLength FocalLength 35, 55, 105, 'spherical' (= Theta S, Insta360)
focusDistance number
focusMeteringMode FocusMeteringMode 'center-spot', 'multi-spot'
focusMode FocusMode
functionalMode FunctionalMode 'standard', 'sleep'
imageAspect string '16:9', '3:2', 'a size'
imageQuality string 'fine', 'raw,fine', 'raw' (comma-separated)
imageSize string 'L', 'M', 'S', '1024x768'
iso ISO 160, 3200, 'auto'
liveviewEnabled boolean
liveviewMagnifyRatio number
liveviewSize string
manualFocusOptions ManualFocusOption[] ['near:2', 'near:1', 'far:1', 'far:2'] (3 at max speed)
model string
sharpness number
shutterSpeed string '30', '1.5', '1/200', '1/6400'
timelapseInterval number
timelapseNumber number
whiteBalance WhiteBalance 'auto', 'cloud', 'daylight'...

Getter/Setter

You can retrieve and modify configs by two ways shown below:

// 1. Specify a kind of config as argument
tethr.get('<configName>'): Promise<ConfigType | null>
tethr.set('<configName>'): Promise<Result>

// 1. Directly call a getter/setter methods defined per config
tethr.get<ConfigName>(): Promise<ConfigType | null>
tethr.set<ConfigName>(): Promise<Result>

interface Result {
	status: 'ok' | 'unsupported' | 'invalid parameter' | 'busy' | 'general error'
}

// '<configName>' is a name of config written in camelCase ('batteryLevel'),
// and <ConfigName> in CapitalCase (BatteryLevel)

Config Discriptor

If you also want to know an information of config such as writability and valid options, you can use tethr.getDesc('<configName>') or tethr.getConfigNameDesc methods. These return descriptor object.

interface ConfigDesc<ConfigType> {
	writable: boolean
	value: ConfigType | null
	option?:
		| {type: 'enum'; values: ConfigType[]}
		| {type: 'range'; min: ConfigType; max: ConfigType; step: ConfigType}
}

Watching Config Changes

Whenever a value of configuration is changed, correspoinding ${configName}Changed event will be fired. And since Tethr class inherits from EventEmitter, you can monitor the value change as follows:

function callback(desc: ConfigDesc<Aperture>) {
	console.log(`Current aperture=${desc.value}`)
}

// Register the callback
tethr.on('apertureChanged', callback)

// Or watch once
tethr.once('shutterSpeedChanged', callback)

// Delete event listener
tethr.off('apertureChanged', callback)

A event ${configName}Changed is sent out in the case:

  • When you manually set the value of config itself.
  • When you modify other configs which will affect the config value as a side effect
    (Setting 'whiteBalance' to 'auto' makes 'colorTemperature' readonly, for instance)
  • When users change settings by camera buttons / dials physically.

Development Environment

git clone https://github.com/baku89/tethr tethr
cd tethr
yarn install
yarn dev # Then open https://localhost:1234 with a browser

tethr's People

Contributors

baku89 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.