Skip to content
main
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


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 takePictureResult = await cam.takePicture({download: true})

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

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
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

About

JavaScript/TypeScript library built on top of WebUSB for controlling digital cameras from browsers.

Topics

Resources

License

Releases

No releases published

Packages

No packages published