node-libcamera 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,103 +1,55 @@
1
- # TSDX User Guide
1
+ # node-libcamera 📷
2
2
 
3
- Congrats! You just saved yourself hours of work by bootstrapping this project with TSDX. Let’s get you oriented with what’s here and how to use it.
3
+ A set of wrapper functions for the native [Raspberry Pi `libcamera` API](https://www.raspberrypi.com/documentation/accessories/camera.html).
4
4
 
5
- > This TSDX setup is meant for developing libraries (not apps!) that can be published to NPM. If you’re looking to build a Node app, you could use `ts-node-dev`, plain `ts-node`, or simple `tsc`.
5
+ _Open to any and all contributions!_
6
6
 
7
- > If you’re new to TypeScript, checkout [this handy cheatsheet](https://devhints.io/typescript)
8
-
9
- ## Commands
10
-
11
- TSDX scaffolds your new library inside `/src`.
12
-
13
- To run TSDX, use:
7
+ ## Installation
14
8
 
15
9
  ```bash
16
- npm start # or yarn start
10
+ npm install node-libcamera
17
11
  ```
18
12
 
19
- This builds to `/dist` and runs the project in watch mode so any edits you save inside `src` causes a rebuild to `/dist`.
20
-
21
- To do a one-off build, use `npm run build` or `yarn build`.
22
-
23
- To run tests, use `npm test` or `yarn test`.
24
-
25
- ## Configuration
26
-
27
- Code quality is set up for you with `prettier`, `husky`, and `lint-staged`. Adjust the respective fields in `package.json` accordingly.
28
-
29
- ### Jest
13
+ ## Usage
30
14
 
31
- Jest tests are set up to run with `npm test` or `yarn test`.
15
+ ### [`libcamera-still`](https://www.raspberrypi.com/documentation/accessories/camera.html#libcamera-still)
32
16
 
33
- ### Bundle Analysis
17
+ Capture an image!
34
18
 
35
- [`size-limit`](https://github.com/ai/size-limit) is set up to calculate the real cost of your library with `npm run size` and visualize the bundle with `npm run analyze`.
36
-
37
- #### Setup Files
38
-
39
- This is the folder structure we set up for you:
40
-
41
- ```txt
42
- /src
43
- index.tsx # EDIT THIS
44
- /test
45
- blah.test.tsx # EDIT THIS
46
- .gitignore
47
- package.json
48
- README.md # EDIT THIS
49
- tsconfig.json
19
+ ```js
20
+ const { still } = require('node-libcamera')
21
+
22
+ // basic example
23
+ still({ output: 'test.jpg' })
24
+ .then((result) => /* 📸 */ )
25
+ .catch((error) => /* 🐛 */ )
26
+
27
+ // example with options
28
+ still({
29
+ output: 'images/test.jpg', // output file path
30
+ timeout: 2000, // timeout before taking the picture
31
+ width: 640, // image width
32
+ height: 480, // image height
33
+ })
34
+ .then((result) => /* 📸 */ )
35
+ .catch((error) => /* 🐛 */ )
50
36
  ```
51
37
 
52
- ### Rollup
53
-
54
- TSDX uses [Rollup](https://rollupjs.org) as a bundler and generates multiple rollup configs for various module formats and build settings. See [Optimizations](#optimizations) for details.
55
-
56
- ### TypeScript
57
-
58
- `tsconfig.json` is set up to interpret `dom` and `esnext` types, as well as `react` for `jsx`. Adjust according to your needs.
59
-
60
- ## Continuous Integration
38
+ ### [`libcamera-vid`](https://www.raspberrypi.com/documentation/accessories/camera.html#libcamera-vid)
61
39
 
62
- ### GitHub Actions
63
-
64
- Two actions are added by default:
65
-
66
- - `main` which installs deps w/ cache, lints, tests, and builds on all pushes against a Node and OS matrix
67
- - `size` which comments cost comparison of your library on every pull request using [`size-limit`](https://github.com/ai/size-limit)
68
-
69
- ## Optimizations
70
-
71
- Please see the main `tsdx` [optimizations docs](https://github.com/palmerhq/tsdx#optimizations). In particular, know that you can take advantage of development-only optimizations:
40
+ Record a video!
72
41
 
73
42
  ```js
74
- // ./types/index.d.ts
75
- declare var __DEV__: boolean;
43
+ const { vid } = require('node-libcamera')
76
44
 
77
- // inside your code...
78
- if (__DEV__) {
79
- console.log('foo');
80
- }
45
+ // record a 10s video
46
+ vid({ output: 'test.h264', timeout: 10000, 'save-pts': 'timestamps.txt' })
47
+ .then((result) => /* 🎥 */ )
48
+ .catch((error) => /* 🐛 */ )
81
49
  ```
82
50
 
83
- You can also choose to install and use [invariant](https://github.com/palmerhq/tsdx#invariant) and [warning](https://github.com/palmerhq/tsdx#warning) functions.
84
-
85
- ## Module Formats
86
-
87
- CJS, ESModules, and UMD module formats are supported.
88
-
89
- The appropriate paths are configured in `package.json` and `dist/index.js` accordingly. Please report if any issues are found.
90
-
91
- ## Named Exports
51
+ Note: this will result in an unpackaged video bistream, it is not wrapped in any kind of container format (such as an mp4 file). The `save-pts` option can be used to output frame timestamps so that the bitstream can subsequently be converted into an appropriate format using a tool like `mkvmerge`.
92
52
 
93
- Per Palmer Group guidelines, [always use named exports.](https://github.com/palmerhq/typescript#exports) Code split inside your React app instead of your React library.
94
-
95
- ## Including Styles
96
-
97
- There are many ways to ship styles, including with CSS-in-JS. TSDX has no opinion on this, configure how you like.
98
-
99
- For vanilla CSS, you can include it at the root directory and add it to the `files` section in your `package.json`, so that it can be imported separately by your users and run through their bundler's loader.
100
-
101
- ## Publishing to NPM
102
-
103
- We recommend using [np](https://github.com/sindresorhus/np).
53
+ ```bash
54
+ mkvmerge -o test.mkv --timecodes 0:timestamps.txt test.h264
55
+ ```
package/dist/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  import { LibCamera } from './options';
2
- export declare function snap(options: LibCamera.OptionsObject): Promise<unknown>;
2
+ export declare function jpeg(options: Partial<LibCamera.OptionsObject>): string | Promise<unknown>;
3
+ export declare function still(options: Partial<LibCamera.OptionsObject>): string | Promise<unknown>;
4
+ export declare function vid(options: Partial<LibCamera.OptionsObject>): string | Promise<unknown>;
@@ -2,96 +2,11 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var child_process = require('child_process');
5
+ require('child_process');
6
6
 
7
- var OPTIONS = {
8
- help: {
9
- "short": 'h',
10
- desc: 'Print help information for the application'
11
- },
12
- version: {
13
- desc: 'Print help information for the application'
14
- },
15
- timeout: {
16
- "short": 't',
17
- desc: 'Delay before application stops automatically <milliseconds>',
18
- validator: function validator(val) {
19
- return typeof val === 'number';
20
- },
21
- convert: function convert(val) {
22
- return val.toString();
23
- }
24
- },
25
- preview: {
26
- "short": 'p',
27
- desc: 'Preview window settings <x,y,w,h>',
28
- validator: function validator(val) {
29
- return typeof val === 'object' && Boolean((val == null ? void 0 : val.x) && (val == null ? void 0 : val.y) && (val == null ? void 0 : val.width) && (val == null ? void 0 : val.height));
30
- },
31
- convert: function convert(val) {
32
- return val.x + "," + val.y + "," + val.width + "," + val.height;
33
- }
34
- },
35
- fullscreen: {
36
- "short": 'f',
37
- desc: 'Fullscreen preview mode'
38
- },
39
- 'qt-preview': {
40
- desc: 'Use Qt-based preview window'
41
- },
42
- nopreview: {
43
- "short": 'n',
44
- desc: 'Do not display a preview window'
45
- },
46
- 'info-text': {
47
- desc: 'Set window title bar text <string>',
48
- validator: function validator(val) {
49
- return typeof val === 'string';
50
- }
51
- },
52
- width: {
53
- desc: 'Capture image width <width>',
54
- validator: function validator(val) {
55
- return typeof val === 'number';
56
- },
57
- convert: function convert(val) {
58
- return val.toString();
59
- }
60
- },
61
- height: {
62
- desc: 'Capture image height <height>',
63
- validator: function validator(val) {
64
- return typeof val === 'number';
65
- },
66
- convert: function convert(val) {
67
- return val.toString();
68
- }
69
- },
70
- 'viewfinder-width': {
71
- desc: 'Capture image width <width>',
72
- validator: function validator(val) {
73
- return typeof val === 'number';
74
- },
75
- convert: function convert(val) {
76
- return val.toString();
77
- }
78
- },
79
- 'viewfinder-height': {
80
- desc: 'Capture image height <height>',
81
- validator: function validator(val) {
82
- return typeof val === 'number';
83
- },
84
- convert: function convert(val) {
85
- return val.toString();
86
- }
87
- },
88
- // ...
89
- output: {
90
- "short": 'o',
91
- desc: 'Output file name <string>',
92
- validator: function validator(val) {
93
- return typeof val === 'string';
94
- }
7
+ var optionConverterMap = {
8
+ preview: function preview(val) {
9
+ return val.x + "," + val.y + "," + val.width + "," + val.height;
95
10
  }
96
11
  };
97
12
 
@@ -99,37 +14,44 @@ function cmd(base, args) {
99
14
  if (base && !args) return base;
100
15
  return base + " " + (args == null ? void 0 : args.join(' '));
101
16
  }
102
- function run(command, options) {
103
- return new Promise(function (resolve, reject) {
104
- child_process.exec(command, options, function (error, stdout, stderr) {
105
- if (stderr || error) reject(stderr || error);
106
- resolve(stdout);
107
- });
108
- });
109
- }
110
17
  function convertOptionsToCmdArgs(options) {
111
18
  var args = [];
112
19
  Object.entries(options).forEach(function (_ref) {
113
20
  var key = _ref[0],
114
21
  val = _ref[1];
115
- var opt = OPTIONS[key];
116
-
117
- if (typeof opt.validator === 'function' && !opt.validator(val)) {
118
- throw new Error("Invalid value for option \"" + key + "\"");
119
- }
120
-
121
- var value = typeof opt.convert === 'function' ? opt.convert(val) : val;
22
+ var converter = optionConverterMap[key];
23
+ var value = typeof converter === 'function' ? converter(val) : val;
122
24
  if (value) args.push("--" + key);
123
- if (value !== true) args.push(value);
25
+ if (value !== true && value != null && value.toString()) args.push(value == null ? void 0 : value.toString());
124
26
  }, true);
125
27
  return args;
126
28
  }
127
29
 
128
- function snap(options) {
30
+ function runLibCamera(bin, options) {
31
+ if (bin === void 0) {
32
+ bin = 'libcamera-still';
33
+ }
34
+
129
35
  var args = convertOptionsToCmdArgs(options);
130
- var command = cmd('libcamera-still', args);
131
- return run(command);
36
+ var command = cmd(bin, args);
37
+
38
+ {
39
+ console.log(command);
40
+ return command;
41
+ }
42
+ }
43
+
44
+ function jpeg(options) {
45
+ return runLibCamera('libcamera-jpeg', options);
46
+ }
47
+ function still(options) {
48
+ return runLibCamera('libcamera-still', options);
49
+ }
50
+ function vid(options) {
51
+ return runLibCamera('libcamera-vid', options);
132
52
  }
133
53
 
134
- exports.snap = snap;
54
+ exports.jpeg = jpeg;
55
+ exports.still = still;
56
+ exports.vid = vid;
135
57
  //# sourceMappingURL=node-libcamera.cjs.development.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"node-libcamera.cjs.development.js","sources":["../src/options.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["export namespace LibCamera {\n export type OptionKeys = typeof OPTION_KEYS[number]\n\n export interface OptionDefinition {\n short?: string\n desc?: string\n validator?: (val: any) => boolean\n convert?: (val: any) => string\n }\n\n export type OptionsObject = {\n [key in OptionKeys]?: any\n }\n\n export interface PreviewOption {\n x: number\n y: number\n width: number\n height: number\n }\n}\n\nexport const OPTION_KEYS = [\n 'help',\n 'version',\n 'timeout',\n 'preview',\n 'fullscreen',\n 'qt-preview',\n 'nopreview',\n 'info-text',\n 'width',\n 'height',\n 'viewfinder-width',\n 'viewfinder-height',\n // ...\n 'output',\n] as const\n\nexport const OPTIONS: Record<\n LibCamera.OptionKeys,\n LibCamera.OptionDefinition\n> = {\n help: {\n short: 'h',\n desc: 'Print help information for the application',\n },\n version: {\n desc: 'Print help information for the application',\n },\n timeout: {\n short: 't',\n desc: 'Delay before application stops automatically <milliseconds>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n preview: {\n short: 'p',\n desc: 'Preview window settings <x,y,w,h>',\n validator(val: LibCamera.PreviewOption) {\n return (\n typeof val === 'object' &&\n Boolean(val?.x && val?.y && val?.width && val?.height)\n )\n },\n convert(val: LibCamera.PreviewOption) {\n return `${val.x},${val.y},${val.width},${val.height}`\n },\n },\n fullscreen: {\n short: 'f',\n desc: 'Fullscreen preview mode',\n },\n 'qt-preview': {\n desc: 'Use Qt-based preview window',\n },\n nopreview: {\n short: 'n',\n desc: 'Do not display a preview window',\n },\n 'info-text': {\n desc: 'Set window title bar text <string>',\n validator: (val: string) => typeof val === 'string',\n },\n width: {\n desc: 'Capture image width <width>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n height: {\n desc: 'Capture image height <height>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n 'viewfinder-width': {\n desc: 'Capture image width <width>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n 'viewfinder-height': {\n desc: 'Capture image height <height>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n\n // ...\n\n output: {\n short: 'o',\n desc: 'Output file name <string>',\n validator: (val: string) => typeof val === 'string',\n },\n} as const\n","import { exec, ExecOptionsWithBufferEncoding } from 'child_process'\nimport { OPTIONS, LibCamera } from './options'\n\nexport function cmd(base: string, args?: string[]): string {\n if (base && !args) return base\n return `${base} ${args?.join(' ')}`\n}\n\nexport function run(command: string, options?: ExecOptionsWithBufferEncoding) {\n return new Promise((resolve, reject) => {\n exec(command, options, (error, stdout, stderr) => {\n if (stderr || error) reject(stderr || error)\n resolve(stdout)\n })\n })\n}\n\nexport function convertOptionsToCmdArgs(\n options: LibCamera.OptionsObject\n): string[] {\n const args: string[] = []\n Object.entries(options).forEach(([key, val]) => {\n const opt = OPTIONS[key as LibCamera.OptionKeys]\n if (typeof opt.validator === 'function' && !opt.validator(val)) {\n throw new Error(`Invalid value for option \"${key}\"`)\n }\n const value = typeof opt.convert === 'function' ? opt.convert(val) : val\n if (value) args.push(`--${key}`)\n if (value !== true) args.push(value)\n }, true)\n return args\n}\n","import { LibCamera } from './options'\nimport { run, cmd, convertOptionsToCmdArgs } from './utils'\n\nexport function snap(options: LibCamera.OptionsObject) {\n const args = convertOptionsToCmdArgs(options)\n const command = cmd('libcamera-still', args)\n return run(command)\n}\n"],"names":["OPTIONS","help","desc","version","timeout","validator","val","convert","toString","preview","Boolean","x","y","width","height","fullscreen","nopreview","output","cmd","base","args","join","run","command","options","Promise","resolve","reject","exec","error","stdout","stderr","convertOptionsToCmdArgs","Object","entries","forEach","key","opt","Error","value","push","snap"],"mappings":"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"}
1
+ {"version":3,"file":"node-libcamera.cjs.development.js","sources":["../src/options.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["export namespace LibCamera {\n export interface CommandLineOptions {\n /**\n * Print help information for the application\n *\n * The `--help` option causes every application to print its full set of command line options with a brief synopsis of each, and then quit.\n **/\n help: boolean\n /**\n * Print out a software version number\n *\n * All `libcamera-apps` will, when they see the `--version` option, print out a version string both for `libcamera` and `libcamera-apps` and then quit.\n */\n version: boolean\n /**\n * Delay before application stops automatically <milliseconds>\n *\n * The `--timeout` option specifies how long the application runs before it stops, whether it is recording a video or showing a preview. In the case of still image capture, the application will show the preview window for this long before capturing the output image.\n *\n * If unspecified, the default value is 5000 (5 seconds). The value zero causes the application to run indefinitely.\n */\n timeout: number\n }\n\n export interface PreviewWindowOptions {\n /**\n * Preview window settings\n *\n * Sets the size and location of the preview window (both X Windows and DRM versions). It does not affect the resolution or aspect ratio of images being requested from the camera. The camera images will be scaled to the size of the preview window for display, and will be pillar/letter-boxed to fit.\n *\n * Example:\n * ```json\n * { \"x\": 100, \"y\": 100, \"width\": 500, \"height\": 500 }\n * ```\n */\n preview: PreviewOption\n /**\n * Fullscreen preview mode\n *\n * Forces the preview window to use the whole screen, and the window will have no border or title bar. Again the image may be pillar/letter-boxed.\n */\n fullscreen: boolean\n /**\n * Use Qt-based preview window\n *\n * The preview window is switched to use the Qt-based implementation. This option is not normally recommended because it no longer uses zero-copy buffer sharing nor GPU acceleration and is therefore very expensive, however, it does support X forwarding (which the other preview implementations do not).\n *\n * The Qt preview window does not support the `--fullscreen` option. Generally it is advised to try and keep the preview window small.\n */\n 'qt-preview': boolean\n /**\n * Do not display a preview window\n *\n * The preview window is suppressed entirely.\n */\n nopreview: boolean\n /**\n * Set window title bar text <string>\n *\n * The supplied string is set as the title of the preview window (when running under X Windows). Additionally the string may contain a number of `%` directives which are substituted with information from the image metadata. The permitted directives are:\n *\n * | Directive | Substitution |\n * | :--------------- | :------------------ |\n * | `%frame` | The sequence number of the frame |\n * | `%fps` | The instantaneous frame rate |\n * | `%exp` | The shutter speed used to capture the image, in microseconds |\n * | `%ag` | The analogue gain applied to the image in the sensor |\n * | `%dg` | The digital gain applied to the image by the ISP |\n * | `%rg` | The gain applied to the red component of each pixel |\n * | `%bg` | The gain applied to the blue component of each pixel |\n * | `%focus` | The focus metric for the image, where a larger value implies a sharper image |\n *\n * When not provided, the `--info-text` string defaults to `\"#%frame (%fps fps) exp %exp ag %ag dg %dg\"`.\n */\n 'info-text': string\n }\n\n export interface CameraResolutionOptions {\n /**\n * Capture image width <width>\n *\n * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.\n *\n * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.\n *\n * For libcamera-hello these parameters have no effect.\n */\n width: number\n /**\n * Capture image height <height>\n *\n * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.\n *\n * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.\n *\n * For libcamera-hello these parameters have no effect.\n */\n height: number\n }\n\n export interface OutputFileOptions {\n /**\n * Output file name <string>\n *\n * `--output` sets the name of the output file to which the output image or video is written. Besides regular file names, this may take the following special values:\n *\n * `-` - write to stdout\n *\n * `udp://` - a string starting with this is taken as a network address for streaming\n *\n * `tcp://` - a string starting with this is taken as a network address for streaming\n *\n * a string containing a `%d` directive is taken as a file name where the format directive is replaced with a count that increments for each file that is opened. Standard C format directive modifiers are permitted.\n */\n output: string\n }\n\n export interface VideoOptions {\n /**\n * Saves timestamp information to the specified file. Useful as an input file to `mkvmerge`.\n */\n 'save-pts': string\n }\n\n export type OptionsObject = CommandLineOptions &\n PreviewWindowOptions &\n CameraResolutionOptions &\n OutputFileOptions &\n VideoOptions\n\n export type OptionKeys = keyof OptionsObject\n export type OptionConverter = (val: any) => string\n\n export interface PreviewOption {\n x: number\n y: number\n width: number\n height: number\n }\n}\n\nexport const optionConverterMap: Partial<Record<\n LibCamera.OptionKeys,\n LibCamera.OptionConverter\n>> = {\n preview(val: LibCamera.PreviewOption) {\n return `${val.x},${val.y},${val.width},${val.height}`\n },\n} as const\n","import { exec, ExecOptionsWithBufferEncoding } from 'child_process'\nimport { optionConverterMap, LibCamera } from './options'\n\nexport function cmd(base: string, args?: string[]): string {\n if (base && !args) return base\n return `${base} ${args?.join(' ')}`\n}\n\nexport function run(command: string, options?: ExecOptionsWithBufferEncoding) {\n return new Promise((resolve, reject) => {\n exec(command, options, (error, stdout, stderr) => {\n if (stderr || error) reject(stderr || error)\n resolve(stdout)\n })\n })\n}\n\nexport function convertOptionsToCmdArgs(\n options: Partial<LibCamera.OptionsObject>\n): string[] {\n const args: string[] = []\n Object.entries(options).forEach(([key, val]) => {\n const converter = optionConverterMap[key as LibCamera.OptionKeys]\n const value = typeof converter === 'function' ? converter(val) : val\n if (value) args.push(`--${key}`)\n if (value !== true && value?.toString()) args.push(value?.toString())\n }, true)\n return args\n}\n","import { LibCamera } from './options'\nimport { run, cmd, convertOptionsToCmdArgs } from './utils'\n\nfunction runLibCamera(\n bin: string = 'libcamera-still',\n options: Partial<LibCamera.OptionsObject>\n) {\n const args = convertOptionsToCmdArgs(options)\n const command = cmd(bin, args)\n if (__DEV__) {\n console.log(command)\n return command\n }\n return run(command)\n}\n\nexport function jpeg(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-jpeg', options)\n}\n\nexport function still(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-still', options)\n}\n\nexport function vid(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-vid', options)\n}\n"],"names":["optionConverterMap","preview","val","x","y","width","height","cmd","base","args","join","convertOptionsToCmdArgs","options","Object","entries","forEach","key","converter","value","push","toString","runLibCamera","bin","command","console","log","jpeg","still","vid"],"mappings":";;;;;;AA6IO,IAAMA,kBAAkB,GAG1B;AACHC,EAAAA,OADG,mBACKC,GADL;AAED,WAAUA,GAAG,CAACC,CAAd,SAAmBD,GAAG,CAACE,CAAvB,SAA4BF,GAAG,CAACG,KAAhC,SAAyCH,GAAG,CAACI,MAA7C;AACD;AAHE,CAHE;;SC1ISC,IAAIC,MAAcC;AAChC,MAAID,IAAI,IAAI,CAACC,IAAb,EAAmB,OAAOD,IAAP;AACnB,SAAUA,IAAV,UAAkBC,IAAlB,oBAAkBA,IAAI,CAAEC,IAAN,CAAW,GAAX,CAAlB;AACD;AAED,SASgBC,wBACdC;AAEA,MAAMH,IAAI,GAAa,EAAvB;AACAI,EAAAA,MAAM,CAACC,OAAP,CAAeF,OAAf,EAAwBG,OAAxB,CAAgC;QAAEC;QAAKd;AACrC,QAAMe,SAAS,GAAGjB,kBAAkB,CAACgB,GAAD,CAApC;AACA,QAAME,KAAK,GAAG,OAAOD,SAAP,KAAqB,UAArB,GAAkCA,SAAS,CAACf,GAAD,CAA3C,GAAmDA,GAAjE;AACA,QAAIgB,KAAJ,EAAWT,IAAI,CAACU,IAAL,QAAeH,GAAf;AACX,QAAIE,KAAK,KAAK,IAAV,IAAkBA,KAAlB,YAAkBA,KAAK,CAAEE,QAAP,EAAtB,EAAyCX,IAAI,CAACU,IAAL,CAAUD,KAAV,oBAAUA,KAAK,CAAEE,QAAP,EAAV;AAC1C,GALD,EAKG,IALH;AAMA,SAAOX,IAAP;AACD;;ACzBD,SAASY,YAAT,CACEC,GADF,EAEEV,OAFF;MACEU;AAAAA,IAAAA,MAAc;;;AAGd,MAAMb,IAAI,GAAGE,uBAAuB,CAACC,OAAD,CAApC;AACA,MAAMW,OAAO,GAAGhB,GAAG,CAACe,GAAD,EAAMb,IAAN,CAAnB;;AACA,EAAa;AACXe,IAAAA,OAAO,CAACC,GAAR,CAAYF,OAAZ;AACA,WAAOA,OAAP;AACD;AAEF;;AAED,SAAgBG,KAAKd;AACnB,SAAOS,YAAY,CAAC,gBAAD,EAAmBT,OAAnB,CAAnB;AACD;AAED,SAAgBe,MAAMf;AACpB,SAAOS,YAAY,CAAC,iBAAD,EAAoBT,OAApB,CAAnB;AACD;AAED,SAAgBgB,IAAIhB;AAClB,SAAOS,YAAY,CAAC,eAAD,EAAkBT,OAAlB,CAAnB;AACD;;;;;;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("child_process"),e={help:{short:"h",desc:"Print help information for the application"},version:{desc:"Print help information for the application"},timeout:{short:"t",desc:"Delay before application stops automatically <milliseconds>",validator:function(t){return"number"==typeof t},convert:function(t){return t.toString()}},preview:{short:"p",desc:"Preview window settings <x,y,w,h>",validator:function(t){return"object"==typeof t&&Boolean((null==t?void 0:t.x)&&(null==t?void 0:t.y)&&(null==t?void 0:t.width)&&(null==t?void 0:t.height))},convert:function(t){return t.x+","+t.y+","+t.width+","+t.height}},fullscreen:{short:"f",desc:"Fullscreen preview mode"},"qt-preview":{desc:"Use Qt-based preview window"},nopreview:{short:"n",desc:"Do not display a preview window"},"info-text":{desc:"Set window title bar text <string>",validator:function(t){return"string"==typeof t}},width:{desc:"Capture image width <width>",validator:function(t){return"number"==typeof t},convert:function(t){return t.toString()}},height:{desc:"Capture image height <height>",validator:function(t){return"number"==typeof t},convert:function(t){return t.toString()}},"viewfinder-width":{desc:"Capture image width <width>",validator:function(t){return"number"==typeof t},convert:function(t){return t.toString()}},"viewfinder-height":{desc:"Capture image height <height>",validator:function(t){return"number"==typeof t},convert:function(t){return t.toString()}},output:{short:"o",desc:"Output file name <string>",validator:function(t){return"string"==typeof t}}};exports.snap=function(n){return r=function(t,e){return e?t+" "+(null==e?void 0:e.join(" ")):t}("libcamera-still",function(t){var n=[];return Object.entries(t).forEach((function(t){var r=t[0],i=t[1],o=e[r];if("function"==typeof o.validator&&!o.validator(i))throw new Error('Invalid value for option "'+r+'"');var u="function"==typeof o.convert?o.convert(i):i;u&&n.push("--"+r),!0!==u&&n.push(u)}),!0),n}(n)),new Promise((function(e,n){t.exec(r,void 0,(function(t,r,i){(i||t)&&n(i||t),e(r)}))}));var r};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("child_process"),n={preview:function(e){return e.x+","+e.y+","+e.width+","+e.height}};function r(r,t){return void 0===r&&(r="libcamera-still"),i=function(e,n){return e&&!n?e:e+" "+(null==n?void 0:n.join(" "))}(r,function(e){var r=[];return Object.entries(e).forEach((function(e){var t=e[0],i=e[1],o=n[t],u="function"==typeof o?o(i):i;u&&r.push("--"+t),!0!==u&&null!=u&&u.toString()&&r.push(null==u?void 0:u.toString())}),!0),r}(t)),new Promise((function(n,r){e.exec(i,void 0,(function(e,t,i){(i||e)&&r(i||e),n(t)}))}));var i}exports.jpeg=function(e){return r("libcamera-jpeg",e)},exports.still=function(e){return r("libcamera-still",e)},exports.vid=function(e){return r("libcamera-vid",e)};
2
2
  //# sourceMappingURL=node-libcamera.cjs.production.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"node-libcamera.cjs.production.min.js","sources":["../src/options.ts","../src/index.ts","../src/utils.ts"],"sourcesContent":["export namespace LibCamera {\n export type OptionKeys = typeof OPTION_KEYS[number]\n\n export interface OptionDefinition {\n short?: string\n desc?: string\n validator?: (val: any) => boolean\n convert?: (val: any) => string\n }\n\n export type OptionsObject = {\n [key in OptionKeys]?: any\n }\n\n export interface PreviewOption {\n x: number\n y: number\n width: number\n height: number\n }\n}\n\nexport const OPTION_KEYS = [\n 'help',\n 'version',\n 'timeout',\n 'preview',\n 'fullscreen',\n 'qt-preview',\n 'nopreview',\n 'info-text',\n 'width',\n 'height',\n 'viewfinder-width',\n 'viewfinder-height',\n // ...\n 'output',\n] as const\n\nexport const OPTIONS: Record<\n LibCamera.OptionKeys,\n LibCamera.OptionDefinition\n> = {\n help: {\n short: 'h',\n desc: 'Print help information for the application',\n },\n version: {\n desc: 'Print help information for the application',\n },\n timeout: {\n short: 't',\n desc: 'Delay before application stops automatically <milliseconds>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n preview: {\n short: 'p',\n desc: 'Preview window settings <x,y,w,h>',\n validator(val: LibCamera.PreviewOption) {\n return (\n typeof val === 'object' &&\n Boolean(val?.x && val?.y && val?.width && val?.height)\n )\n },\n convert(val: LibCamera.PreviewOption) {\n return `${val.x},${val.y},${val.width},${val.height}`\n },\n },\n fullscreen: {\n short: 'f',\n desc: 'Fullscreen preview mode',\n },\n 'qt-preview': {\n desc: 'Use Qt-based preview window',\n },\n nopreview: {\n short: 'n',\n desc: 'Do not display a preview window',\n },\n 'info-text': {\n desc: 'Set window title bar text <string>',\n validator: (val: string) => typeof val === 'string',\n },\n width: {\n desc: 'Capture image width <width>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n height: {\n desc: 'Capture image height <height>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n 'viewfinder-width': {\n desc: 'Capture image width <width>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n 'viewfinder-height': {\n desc: 'Capture image height <height>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n\n // ...\n\n output: {\n short: 'o',\n desc: 'Output file name <string>',\n validator: (val: string) => typeof val === 'string',\n },\n} as const\n","import { LibCamera } from './options'\nimport { run, cmd, convertOptionsToCmdArgs } from './utils'\n\nexport function snap(options: LibCamera.OptionsObject) {\n const args = convertOptionsToCmdArgs(options)\n const command = cmd('libcamera-still', args)\n return run(command)\n}\n","import { exec, ExecOptionsWithBufferEncoding } from 'child_process'\nimport { OPTIONS, LibCamera } from './options'\n\nexport function cmd(base: string, args?: string[]): string {\n if (base && !args) return base\n return `${base} ${args?.join(' ')}`\n}\n\nexport function run(command: string, options?: ExecOptionsWithBufferEncoding) {\n return new Promise((resolve, reject) => {\n exec(command, options, (error, stdout, stderr) => {\n if (stderr || error) reject(stderr || error)\n resolve(stdout)\n })\n })\n}\n\nexport function convertOptionsToCmdArgs(\n options: LibCamera.OptionsObject\n): string[] {\n const args: string[] = []\n Object.entries(options).forEach(([key, val]) => {\n const opt = OPTIONS[key as LibCamera.OptionKeys]\n if (typeof opt.validator === 'function' && !opt.validator(val)) {\n throw new Error(`Invalid value for option \"${key}\"`)\n }\n const value = typeof opt.convert === 'function' ? opt.convert(val) : val\n if (value) args.push(`--${key}`)\n if (value !== true) args.push(value)\n }, true)\n return args\n}\n"],"names":["OPTIONS","help","desc","version","timeout","validator","val","convert","toString","preview","Boolean","x","y","width","height","fullscreen","nopreview","output","options","command","base","args","join","cmd","Object","entries","forEach","key","opt","Error","value","push","convertOptionsToCmdArgs","Promise","resolve","reject","exec","run","error","stdout","stderr"],"mappings":"mGAuCaA,EAGT,CACFC,KAAM,OACG,IACPC,KAAM,8CAERC,QAAS,CACPD,KAAM,8CAERE,QAAS,OACA,IACPF,KAAM,8DACNG,UAAW,SAACC,SAA+B,iBAARA,GACnCC,QAAS,SAACD,UAAgBA,EAAIE,aAEhCC,QAAS,OACA,IACPP,KAAM,oCACNG,mBAAUC,SAES,iBAARA,GACPI,eAAQJ,SAAAA,EAAKK,WAAKL,SAAAA,EAAKM,WAAKN,SAAAA,EAAKO,eAASP,SAAAA,EAAKQ,UAGnDP,iBAAQD,UACIA,EAAIK,MAAKL,EAAIM,MAAKN,EAAIO,UAASP,EAAIQ,SAGjDC,WAAY,OACH,IACPb,KAAM,wCAEM,CACZA,KAAM,+BAERc,UAAW,OACF,IACPd,KAAM,+CAEK,CACXA,KAAM,qCACNG,UAAW,SAACC,SAA+B,iBAARA,IAErCO,MAAO,CACLX,KAAM,8BACNG,UAAW,SAACC,SAA+B,iBAARA,GACnCC,QAAS,SAACD,UAAgBA,EAAIE,aAEhCM,OAAQ,CACNZ,KAAM,gCACNG,UAAW,SAACC,SAA+B,iBAARA,GACnCC,QAAS,SAACD,UAAgBA,EAAIE,gCAEZ,CAClBN,KAAM,8BACNG,UAAW,SAACC,SAA+B,iBAARA,GACnCC,QAAS,SAACD,UAAgBA,EAAIE,iCAEX,CACnBN,KAAM,gCACNG,UAAW,SAACC,SAA+B,iBAARA,GACnCC,QAAS,SAACD,UAAgBA,EAAIE,aAKhCS,OAAQ,OACC,IACPf,KAAM,4BACNG,UAAW,SAACC,SAA+B,iBAARA,2BC3GlBY,UCKDC,WALAC,EAAcC,UACnBA,EACHD,aAAQC,SAAAA,EAAMC,KAAK,MADHF,EDCVG,CAAI,2BCapBL,OAEMG,EAAiB,UACvBG,OAAOC,QAAQP,GAASQ,SAAQ,gBAAEC,OAAKrB,OAC/BsB,EAAM5B,EAAQ2B,MACS,mBAAlBC,EAAIvB,YAA6BuB,EAAIvB,UAAUC,SAClD,IAAIuB,mCAAmCF,WAEzCG,EAA+B,mBAAhBF,EAAIrB,QAAyBqB,EAAIrB,QAAQD,GAAOA,EACjEwB,GAAOT,EAAKU,UAAUJ,IACZ,IAAVG,GAAgBT,EAAKU,KAAKD,MAC7B,GACIT,ED1BMW,CAAwBd,ICK9B,IAAIe,SAAQ,SAACC,EAASC,GAC3BC,OAAKjB,ODJAkB,GCIkB,SAACC,EAAOC,EAAQC,IACjCA,GAAUF,IAAOH,EAAOK,GAAUF,GACtCJ,EAAQK,aAJMpB"}
1
+ {"version":3,"file":"node-libcamera.cjs.production.min.js","sources":["../src/options.ts","../src/index.ts","../src/utils.ts"],"sourcesContent":["export namespace LibCamera {\n export interface CommandLineOptions {\n /**\n * Print help information for the application\n *\n * The `--help` option causes every application to print its full set of command line options with a brief synopsis of each, and then quit.\n **/\n help: boolean\n /**\n * Print out a software version number\n *\n * All `libcamera-apps` will, when they see the `--version` option, print out a version string both for `libcamera` and `libcamera-apps` and then quit.\n */\n version: boolean\n /**\n * Delay before application stops automatically <milliseconds>\n *\n * The `--timeout` option specifies how long the application runs before it stops, whether it is recording a video or showing a preview. In the case of still image capture, the application will show the preview window for this long before capturing the output image.\n *\n * If unspecified, the default value is 5000 (5 seconds). The value zero causes the application to run indefinitely.\n */\n timeout: number\n }\n\n export interface PreviewWindowOptions {\n /**\n * Preview window settings\n *\n * Sets the size and location of the preview window (both X Windows and DRM versions). It does not affect the resolution or aspect ratio of images being requested from the camera. The camera images will be scaled to the size of the preview window for display, and will be pillar/letter-boxed to fit.\n *\n * Example:\n * ```json\n * { \"x\": 100, \"y\": 100, \"width\": 500, \"height\": 500 }\n * ```\n */\n preview: PreviewOption\n /**\n * Fullscreen preview mode\n *\n * Forces the preview window to use the whole screen, and the window will have no border or title bar. Again the image may be pillar/letter-boxed.\n */\n fullscreen: boolean\n /**\n * Use Qt-based preview window\n *\n * The preview window is switched to use the Qt-based implementation. This option is not normally recommended because it no longer uses zero-copy buffer sharing nor GPU acceleration and is therefore very expensive, however, it does support X forwarding (which the other preview implementations do not).\n *\n * The Qt preview window does not support the `--fullscreen` option. Generally it is advised to try and keep the preview window small.\n */\n 'qt-preview': boolean\n /**\n * Do not display a preview window\n *\n * The preview window is suppressed entirely.\n */\n nopreview: boolean\n /**\n * Set window title bar text <string>\n *\n * The supplied string is set as the title of the preview window (when running under X Windows). Additionally the string may contain a number of `%` directives which are substituted with information from the image metadata. The permitted directives are:\n *\n * | Directive | Substitution |\n * | :--------------- | :------------------ |\n * | `%frame` | The sequence number of the frame |\n * | `%fps` | The instantaneous frame rate |\n * | `%exp` | The shutter speed used to capture the image, in microseconds |\n * | `%ag` | The analogue gain applied to the image in the sensor |\n * | `%dg` | The digital gain applied to the image by the ISP |\n * | `%rg` | The gain applied to the red component of each pixel |\n * | `%bg` | The gain applied to the blue component of each pixel |\n * | `%focus` | The focus metric for the image, where a larger value implies a sharper image |\n *\n * When not provided, the `--info-text` string defaults to `\"#%frame (%fps fps) exp %exp ag %ag dg %dg\"`.\n */\n 'info-text': string\n }\n\n export interface CameraResolutionOptions {\n /**\n * Capture image width <width>\n *\n * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.\n *\n * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.\n *\n * For libcamera-hello these parameters have no effect.\n */\n width: number\n /**\n * Capture image height <height>\n *\n * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.\n *\n * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.\n *\n * For libcamera-hello these parameters have no effect.\n */\n height: number\n }\n\n export interface OutputFileOptions {\n /**\n * Output file name <string>\n *\n * `--output` sets the name of the output file to which the output image or video is written. Besides regular file names, this may take the following special values:\n *\n * `-` - write to stdout\n *\n * `udp://` - a string starting with this is taken as a network address for streaming\n *\n * `tcp://` - a string starting with this is taken as a network address for streaming\n *\n * a string containing a `%d` directive is taken as a file name where the format directive is replaced with a count that increments for each file that is opened. Standard C format directive modifiers are permitted.\n */\n output: string\n }\n\n export interface VideoOptions {\n /**\n * Saves timestamp information to the specified file. Useful as an input file to `mkvmerge`.\n */\n 'save-pts': string\n }\n\n export type OptionsObject = CommandLineOptions &\n PreviewWindowOptions &\n CameraResolutionOptions &\n OutputFileOptions &\n VideoOptions\n\n export type OptionKeys = keyof OptionsObject\n export type OptionConverter = (val: any) => string\n\n export interface PreviewOption {\n x: number\n y: number\n width: number\n height: number\n }\n}\n\nexport const optionConverterMap: Partial<Record<\n LibCamera.OptionKeys,\n LibCamera.OptionConverter\n>> = {\n preview(val: LibCamera.PreviewOption) {\n return `${val.x},${val.y},${val.width},${val.height}`\n },\n} as const\n","import { LibCamera } from './options'\nimport { run, cmd, convertOptionsToCmdArgs } from './utils'\n\nfunction runLibCamera(\n bin: string = 'libcamera-still',\n options: Partial<LibCamera.OptionsObject>\n) {\n const args = convertOptionsToCmdArgs(options)\n const command = cmd(bin, args)\n if (__DEV__) {\n console.log(command)\n return command\n }\n return run(command)\n}\n\nexport function jpeg(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-jpeg', options)\n}\n\nexport function still(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-still', options)\n}\n\nexport function vid(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-vid', options)\n}\n","import { exec, ExecOptionsWithBufferEncoding } from 'child_process'\nimport { optionConverterMap, LibCamera } from './options'\n\nexport function cmd(base: string, args?: string[]): string {\n if (base && !args) return base\n return `${base} ${args?.join(' ')}`\n}\n\nexport function run(command: string, options?: ExecOptionsWithBufferEncoding) {\n return new Promise((resolve, reject) => {\n exec(command, options, (error, stdout, stderr) => {\n if (stderr || error) reject(stderr || error)\n resolve(stdout)\n })\n })\n}\n\nexport function convertOptionsToCmdArgs(\n options: Partial<LibCamera.OptionsObject>\n): string[] {\n const args: string[] = []\n Object.entries(options).forEach(([key, val]) => {\n const converter = optionConverterMap[key as LibCamera.OptionKeys]\n const value = typeof converter === 'function' ? converter(val) : val\n if (value) args.push(`--${key}`)\n if (value !== true && value?.toString()) args.push(value?.toString())\n }, true)\n return args\n}\n"],"names":["optionConverterMap","preview","val","x","y","width","height","runLibCamera","bin","options","command","base","args","join","cmd","Object","entries","forEach","key","converter","value","push","toString","convertOptionsToCmdArgs","Promise","resolve","reject","exec","run","error","stdout","stderr"],"mappings":"mGA6IaA,EAGR,CACHC,iBAAQC,UACIA,EAAIC,MAAKD,EAAIE,MAAKF,EAAIG,UAASH,EAAII,SC/IjD,SAASC,EACPC,EACAC,mBADAD,IAAAA,EAAc,mBCIIE,WALAC,EAAcC,UAC5BD,IAASC,EAAaD,EAChBA,aAAQC,SAAAA,EAAMC,KAAK,MDGbC,CAAIN,WCUpBC,OAEMG,EAAiB,UACvBG,OAAOC,QAAQP,GAASQ,SAAQ,gBAAEC,OAAKhB,OAC/BiB,EAAYnB,EAAmBkB,GAC/BE,EAA6B,mBAAdD,EAA2BA,EAAUjB,GAAOA,EAC7DkB,GAAOR,EAAKS,UAAUH,IACZ,IAAVE,SAAkBA,GAAAA,EAAOE,YAAYV,EAAKS,WAAKD,SAAAA,EAAOE,eACzD,GACIV,EDpBMW,CAAwBd,ICE9B,IAAIe,SAAQ,SAACC,EAASC,GAC3BC,OAAKjB,ODGAkB,GCHkB,SAACC,EAAOC,EAAQC,IACjCA,GAAUF,IAAOH,EAAOK,GAAUF,GACtCJ,EAAQK,aAJMpB,wBDQCD,UACZF,EAAa,iBAAkBE,2BAGlBA,UACbF,EAAa,kBAAmBE,yBAGrBA,UACXF,EAAa,gBAAiBE"}
@@ -1,93 +1,8 @@
1
1
  import { exec } from 'child_process';
2
2
 
3
- var OPTIONS = {
4
- help: {
5
- "short": 'h',
6
- desc: 'Print help information for the application'
7
- },
8
- version: {
9
- desc: 'Print help information for the application'
10
- },
11
- timeout: {
12
- "short": 't',
13
- desc: 'Delay before application stops automatically <milliseconds>',
14
- validator: function validator(val) {
15
- return typeof val === 'number';
16
- },
17
- convert: function convert(val) {
18
- return val.toString();
19
- }
20
- },
21
- preview: {
22
- "short": 'p',
23
- desc: 'Preview window settings <x,y,w,h>',
24
- validator: function validator(val) {
25
- return typeof val === 'object' && Boolean((val == null ? void 0 : val.x) && (val == null ? void 0 : val.y) && (val == null ? void 0 : val.width) && (val == null ? void 0 : val.height));
26
- },
27
- convert: function convert(val) {
28
- return val.x + "," + val.y + "," + val.width + "," + val.height;
29
- }
30
- },
31
- fullscreen: {
32
- "short": 'f',
33
- desc: 'Fullscreen preview mode'
34
- },
35
- 'qt-preview': {
36
- desc: 'Use Qt-based preview window'
37
- },
38
- nopreview: {
39
- "short": 'n',
40
- desc: 'Do not display a preview window'
41
- },
42
- 'info-text': {
43
- desc: 'Set window title bar text <string>',
44
- validator: function validator(val) {
45
- return typeof val === 'string';
46
- }
47
- },
48
- width: {
49
- desc: 'Capture image width <width>',
50
- validator: function validator(val) {
51
- return typeof val === 'number';
52
- },
53
- convert: function convert(val) {
54
- return val.toString();
55
- }
56
- },
57
- height: {
58
- desc: 'Capture image height <height>',
59
- validator: function validator(val) {
60
- return typeof val === 'number';
61
- },
62
- convert: function convert(val) {
63
- return val.toString();
64
- }
65
- },
66
- 'viewfinder-width': {
67
- desc: 'Capture image width <width>',
68
- validator: function validator(val) {
69
- return typeof val === 'number';
70
- },
71
- convert: function convert(val) {
72
- return val.toString();
73
- }
74
- },
75
- 'viewfinder-height': {
76
- desc: 'Capture image height <height>',
77
- validator: function validator(val) {
78
- return typeof val === 'number';
79
- },
80
- convert: function convert(val) {
81
- return val.toString();
82
- }
83
- },
84
- // ...
85
- output: {
86
- "short": 'o',
87
- desc: 'Output file name <string>',
88
- validator: function validator(val) {
89
- return typeof val === 'string';
90
- }
3
+ var optionConverterMap = {
4
+ preview: function preview(val) {
5
+ return val.x + "," + val.y + "," + val.width + "," + val.height;
91
6
  }
92
7
  };
93
8
 
@@ -108,24 +23,39 @@ function convertOptionsToCmdArgs(options) {
108
23
  Object.entries(options).forEach(function (_ref) {
109
24
  var key = _ref[0],
110
25
  val = _ref[1];
111
- var opt = OPTIONS[key];
112
-
113
- if (typeof opt.validator === 'function' && !opt.validator(val)) {
114
- throw new Error("Invalid value for option \"" + key + "\"");
115
- }
116
-
117
- var value = typeof opt.convert === 'function' ? opt.convert(val) : val;
26
+ var converter = optionConverterMap[key];
27
+ var value = typeof converter === 'function' ? converter(val) : val;
118
28
  if (value) args.push("--" + key);
119
- if (value !== true) args.push(value);
29
+ if (value !== true && value != null && value.toString()) args.push(value == null ? void 0 : value.toString());
120
30
  }, true);
121
31
  return args;
122
32
  }
123
33
 
124
- function snap(options) {
34
+ function runLibCamera(bin, options) {
35
+ if (bin === void 0) {
36
+ bin = 'libcamera-still';
37
+ }
38
+
125
39
  var args = convertOptionsToCmdArgs(options);
126
- var command = cmd('libcamera-still', args);
40
+ var command = cmd(bin, args);
41
+
42
+ if (process.env.NODE_ENV !== "production") {
43
+ console.log(command);
44
+ return command;
45
+ }
46
+
127
47
  return run(command);
128
48
  }
129
49
 
130
- export { snap };
50
+ function jpeg(options) {
51
+ return runLibCamera('libcamera-jpeg', options);
52
+ }
53
+ function still(options) {
54
+ return runLibCamera('libcamera-still', options);
55
+ }
56
+ function vid(options) {
57
+ return runLibCamera('libcamera-vid', options);
58
+ }
59
+
60
+ export { jpeg, still, vid };
131
61
  //# sourceMappingURL=node-libcamera.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"node-libcamera.esm.js","sources":["../src/options.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["export namespace LibCamera {\n export type OptionKeys = typeof OPTION_KEYS[number]\n\n export interface OptionDefinition {\n short?: string\n desc?: string\n validator?: (val: any) => boolean\n convert?: (val: any) => string\n }\n\n export type OptionsObject = {\n [key in OptionKeys]?: any\n }\n\n export interface PreviewOption {\n x: number\n y: number\n width: number\n height: number\n }\n}\n\nexport const OPTION_KEYS = [\n 'help',\n 'version',\n 'timeout',\n 'preview',\n 'fullscreen',\n 'qt-preview',\n 'nopreview',\n 'info-text',\n 'width',\n 'height',\n 'viewfinder-width',\n 'viewfinder-height',\n // ...\n 'output',\n] as const\n\nexport const OPTIONS: Record<\n LibCamera.OptionKeys,\n LibCamera.OptionDefinition\n> = {\n help: {\n short: 'h',\n desc: 'Print help information for the application',\n },\n version: {\n desc: 'Print help information for the application',\n },\n timeout: {\n short: 't',\n desc: 'Delay before application stops automatically <milliseconds>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n preview: {\n short: 'p',\n desc: 'Preview window settings <x,y,w,h>',\n validator(val: LibCamera.PreviewOption) {\n return (\n typeof val === 'object' &&\n Boolean(val?.x && val?.y && val?.width && val?.height)\n )\n },\n convert(val: LibCamera.PreviewOption) {\n return `${val.x},${val.y},${val.width},${val.height}`\n },\n },\n fullscreen: {\n short: 'f',\n desc: 'Fullscreen preview mode',\n },\n 'qt-preview': {\n desc: 'Use Qt-based preview window',\n },\n nopreview: {\n short: 'n',\n desc: 'Do not display a preview window',\n },\n 'info-text': {\n desc: 'Set window title bar text <string>',\n validator: (val: string) => typeof val === 'string',\n },\n width: {\n desc: 'Capture image width <width>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n height: {\n desc: 'Capture image height <height>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n 'viewfinder-width': {\n desc: 'Capture image width <width>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n 'viewfinder-height': {\n desc: 'Capture image height <height>',\n validator: (val: number) => typeof val === 'number',\n convert: (val: number) => val.toString(),\n },\n\n // ...\n\n output: {\n short: 'o',\n desc: 'Output file name <string>',\n validator: (val: string) => typeof val === 'string',\n },\n} as const\n","import { exec, ExecOptionsWithBufferEncoding } from 'child_process'\nimport { OPTIONS, LibCamera } from './options'\n\nexport function cmd(base: string, args?: string[]): string {\n if (base && !args) return base\n return `${base} ${args?.join(' ')}`\n}\n\nexport function run(command: string, options?: ExecOptionsWithBufferEncoding) {\n return new Promise((resolve, reject) => {\n exec(command, options, (error, stdout, stderr) => {\n if (stderr || error) reject(stderr || error)\n resolve(stdout)\n })\n })\n}\n\nexport function convertOptionsToCmdArgs(\n options: LibCamera.OptionsObject\n): string[] {\n const args: string[] = []\n Object.entries(options).forEach(([key, val]) => {\n const opt = OPTIONS[key as LibCamera.OptionKeys]\n if (typeof opt.validator === 'function' && !opt.validator(val)) {\n throw new Error(`Invalid value for option \"${key}\"`)\n }\n const value = typeof opt.convert === 'function' ? opt.convert(val) : val\n if (value) args.push(`--${key}`)\n if (value !== true) args.push(value)\n }, true)\n return args\n}\n","import { LibCamera } from './options'\nimport { run, cmd, convertOptionsToCmdArgs } from './utils'\n\nexport function snap(options: LibCamera.OptionsObject) {\n const args = convertOptionsToCmdArgs(options)\n const command = cmd('libcamera-still', args)\n return run(command)\n}\n"],"names":["OPTIONS","help","desc","version","timeout","validator","val","convert","toString","preview","Boolean","x","y","width","height","fullscreen","nopreview","output","cmd","base","args","join","run","command","options","Promise","resolve","reject","exec","error","stdout","stderr","convertOptionsToCmdArgs","Object","entries","forEach","key","opt","Error","value","push","snap"],"mappings":"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"}
1
+ {"version":3,"file":"node-libcamera.esm.js","sources":["../src/options.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["export namespace LibCamera {\n export interface CommandLineOptions {\n /**\n * Print help information for the application\n *\n * The `--help` option causes every application to print its full set of command line options with a brief synopsis of each, and then quit.\n **/\n help: boolean\n /**\n * Print out a software version number\n *\n * All `libcamera-apps` will, when they see the `--version` option, print out a version string both for `libcamera` and `libcamera-apps` and then quit.\n */\n version: boolean\n /**\n * Delay before application stops automatically <milliseconds>\n *\n * The `--timeout` option specifies how long the application runs before it stops, whether it is recording a video or showing a preview. In the case of still image capture, the application will show the preview window for this long before capturing the output image.\n *\n * If unspecified, the default value is 5000 (5 seconds). The value zero causes the application to run indefinitely.\n */\n timeout: number\n }\n\n export interface PreviewWindowOptions {\n /**\n * Preview window settings\n *\n * Sets the size and location of the preview window (both X Windows and DRM versions). It does not affect the resolution or aspect ratio of images being requested from the camera. The camera images will be scaled to the size of the preview window for display, and will be pillar/letter-boxed to fit.\n *\n * Example:\n * ```json\n * { \"x\": 100, \"y\": 100, \"width\": 500, \"height\": 500 }\n * ```\n */\n preview: PreviewOption\n /**\n * Fullscreen preview mode\n *\n * Forces the preview window to use the whole screen, and the window will have no border or title bar. Again the image may be pillar/letter-boxed.\n */\n fullscreen: boolean\n /**\n * Use Qt-based preview window\n *\n * The preview window is switched to use the Qt-based implementation. This option is not normally recommended because it no longer uses zero-copy buffer sharing nor GPU acceleration and is therefore very expensive, however, it does support X forwarding (which the other preview implementations do not).\n *\n * The Qt preview window does not support the `--fullscreen` option. Generally it is advised to try and keep the preview window small.\n */\n 'qt-preview': boolean\n /**\n * Do not display a preview window\n *\n * The preview window is suppressed entirely.\n */\n nopreview: boolean\n /**\n * Set window title bar text <string>\n *\n * The supplied string is set as the title of the preview window (when running under X Windows). Additionally the string may contain a number of `%` directives which are substituted with information from the image metadata. The permitted directives are:\n *\n * | Directive | Substitution |\n * | :--------------- | :------------------ |\n * | `%frame` | The sequence number of the frame |\n * | `%fps` | The instantaneous frame rate |\n * | `%exp` | The shutter speed used to capture the image, in microseconds |\n * | `%ag` | The analogue gain applied to the image in the sensor |\n * | `%dg` | The digital gain applied to the image by the ISP |\n * | `%rg` | The gain applied to the red component of each pixel |\n * | `%bg` | The gain applied to the blue component of each pixel |\n * | `%focus` | The focus metric for the image, where a larger value implies a sharper image |\n *\n * When not provided, the `--info-text` string defaults to `\"#%frame (%fps fps) exp %exp ag %ag dg %dg\"`.\n */\n 'info-text': string\n }\n\n export interface CameraResolutionOptions {\n /**\n * Capture image width <width>\n *\n * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.\n *\n * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.\n *\n * For libcamera-hello these parameters have no effect.\n */\n width: number\n /**\n * Capture image height <height>\n *\n * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.\n *\n * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.\n *\n * For libcamera-hello these parameters have no effect.\n */\n height: number\n }\n\n export interface OutputFileOptions {\n /**\n * Output file name <string>\n *\n * `--output` sets the name of the output file to which the output image or video is written. Besides regular file names, this may take the following special values:\n *\n * `-` - write to stdout\n *\n * `udp://` - a string starting with this is taken as a network address for streaming\n *\n * `tcp://` - a string starting with this is taken as a network address for streaming\n *\n * a string containing a `%d` directive is taken as a file name where the format directive is replaced with a count that increments for each file that is opened. Standard C format directive modifiers are permitted.\n */\n output: string\n }\n\n export interface VideoOptions {\n /**\n * Saves timestamp information to the specified file. Useful as an input file to `mkvmerge`.\n */\n 'save-pts': string\n }\n\n export type OptionsObject = CommandLineOptions &\n PreviewWindowOptions &\n CameraResolutionOptions &\n OutputFileOptions &\n VideoOptions\n\n export type OptionKeys = keyof OptionsObject\n export type OptionConverter = (val: any) => string\n\n export interface PreviewOption {\n x: number\n y: number\n width: number\n height: number\n }\n}\n\nexport const optionConverterMap: Partial<Record<\n LibCamera.OptionKeys,\n LibCamera.OptionConverter\n>> = {\n preview(val: LibCamera.PreviewOption) {\n return `${val.x},${val.y},${val.width},${val.height}`\n },\n} as const\n","import { exec, ExecOptionsWithBufferEncoding } from 'child_process'\nimport { optionConverterMap, LibCamera } from './options'\n\nexport function cmd(base: string, args?: string[]): string {\n if (base && !args) return base\n return `${base} ${args?.join(' ')}`\n}\n\nexport function run(command: string, options?: ExecOptionsWithBufferEncoding) {\n return new Promise((resolve, reject) => {\n exec(command, options, (error, stdout, stderr) => {\n if (stderr || error) reject(stderr || error)\n resolve(stdout)\n })\n })\n}\n\nexport function convertOptionsToCmdArgs(\n options: Partial<LibCamera.OptionsObject>\n): string[] {\n const args: string[] = []\n Object.entries(options).forEach(([key, val]) => {\n const converter = optionConverterMap[key as LibCamera.OptionKeys]\n const value = typeof converter === 'function' ? converter(val) : val\n if (value) args.push(`--${key}`)\n if (value !== true && value?.toString()) args.push(value?.toString())\n }, true)\n return args\n}\n","import { LibCamera } from './options'\nimport { run, cmd, convertOptionsToCmdArgs } from './utils'\n\nfunction runLibCamera(\n bin: string = 'libcamera-still',\n options: Partial<LibCamera.OptionsObject>\n) {\n const args = convertOptionsToCmdArgs(options)\n const command = cmd(bin, args)\n if (__DEV__) {\n console.log(command)\n return command\n }\n return run(command)\n}\n\nexport function jpeg(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-jpeg', options)\n}\n\nexport function still(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-still', options)\n}\n\nexport function vid(options: Partial<LibCamera.OptionsObject>) {\n return runLibCamera('libcamera-vid', options)\n}\n"],"names":["optionConverterMap","preview","val","x","y","width","height","cmd","base","args","join","run","command","options","Promise","resolve","reject","exec","error","stdout","stderr","convertOptionsToCmdArgs","Object","entries","forEach","key","converter","value","push","toString","runLibCamera","bin","console","log","jpeg","still","vid"],"mappings":";;AA6IO,IAAMA,kBAAkB,GAG1B;AACHC,EAAAA,OADG,mBACKC,GADL;AAED,WAAUA,GAAG,CAACC,CAAd,SAAmBD,GAAG,CAACE,CAAvB,SAA4BF,GAAG,CAACG,KAAhC,SAAyCH,GAAG,CAACI,MAA7C;AACD;AAHE,CAHE;;SC1ISC,IAAIC,MAAcC;AAChC,MAAID,IAAI,IAAI,CAACC,IAAb,EAAmB,OAAOD,IAAP;AACnB,SAAUA,IAAV,UAAkBC,IAAlB,oBAAkBA,IAAI,CAAEC,IAAN,CAAW,GAAX,CAAlB;AACD;AAED,SAAgBC,IAAIC,SAAiBC;AACnC,SAAO,IAAIC,OAAJ,CAAY,UAACC,OAAD,EAAUC,MAAV;AACjBC,IAAAA,IAAI,CAACL,OAAD,EAAUC,OAAV,EAAmB,UAACK,KAAD,EAAQC,MAAR,EAAgBC,MAAhB;AACrB,UAAIA,MAAM,IAAIF,KAAd,EAAqBF,MAAM,CAACI,MAAM,IAAIF,KAAX,CAAN;AACrBH,MAAAA,OAAO,CAACI,MAAD,CAAP;AACD,KAHG,CAAJ;AAID,GALM,CAAP;AAMD;AAED,SAAgBE,wBACdR;AAEA,MAAMJ,IAAI,GAAa,EAAvB;AACAa,EAAAA,MAAM,CAACC,OAAP,CAAeV,OAAf,EAAwBW,OAAxB,CAAgC;QAAEC;QAAKvB;AACrC,QAAMwB,SAAS,GAAG1B,kBAAkB,CAACyB,GAAD,CAApC;AACA,QAAME,KAAK,GAAG,OAAOD,SAAP,KAAqB,UAArB,GAAkCA,SAAS,CAACxB,GAAD,CAA3C,GAAmDA,GAAjE;AACA,QAAIyB,KAAJ,EAAWlB,IAAI,CAACmB,IAAL,QAAeH,GAAf;AACX,QAAIE,KAAK,KAAK,IAAV,IAAkBA,KAAlB,YAAkBA,KAAK,CAAEE,QAAP,EAAtB,EAAyCpB,IAAI,CAACmB,IAAL,CAAUD,KAAV,oBAAUA,KAAK,CAAEE,QAAP,EAAV;AAC1C,GALD,EAKG,IALH;AAMA,SAAOpB,IAAP;AACD;;ACzBD,SAASqB,YAAT,CACEC,GADF,EAEElB,OAFF;MACEkB;AAAAA,IAAAA,MAAc;;;AAGd,MAAMtB,IAAI,GAAGY,uBAAuB,CAACR,OAAD,CAApC;AACA,MAAMD,OAAO,GAAGL,GAAG,CAACwB,GAAD,EAAMtB,IAAN,CAAnB;;AACA,6CAAa;AACXuB,IAAAA,OAAO,CAACC,GAAR,CAAYrB,OAAZ;AACA,WAAOA,OAAP;AACD;;AACD,SAAOD,GAAG,CAACC,OAAD,CAAV;AACD;;AAED,SAAgBsB,KAAKrB;AACnB,SAAOiB,YAAY,CAAC,gBAAD,EAAmBjB,OAAnB,CAAnB;AACD;AAED,SAAgBsB,MAAMtB;AACpB,SAAOiB,YAAY,CAAC,iBAAD,EAAoBjB,OAApB,CAAnB;AACD;AAED,SAAgBuB,IAAIvB;AAClB,SAAOiB,YAAY,CAAC,eAAD,EAAkBjB,OAAlB,CAAnB;AACD;;;;"}
package/dist/options.d.ts CHANGED
@@ -1,14 +1,125 @@
1
1
  export declare namespace LibCamera {
2
- type OptionKeys = typeof OPTION_KEYS[number];
3
- interface OptionDefinition {
4
- short?: string;
5
- desc?: string;
6
- validator?: (val: any) => boolean;
7
- convert?: (val: any) => string;
2
+ interface CommandLineOptions {
3
+ /**
4
+ * Print help information for the application
5
+ *
6
+ * The `--help` option causes every application to print its full set of command line options with a brief synopsis of each, and then quit.
7
+ **/
8
+ help: boolean;
9
+ /**
10
+ * Print out a software version number
11
+ *
12
+ * All `libcamera-apps` will, when they see the `--version` option, print out a version string both for `libcamera` and `libcamera-apps` and then quit.
13
+ */
14
+ version: boolean;
15
+ /**
16
+ * Delay before application stops automatically <milliseconds>
17
+ *
18
+ * The `--timeout` option specifies how long the application runs before it stops, whether it is recording a video or showing a preview. In the case of still image capture, the application will show the preview window for this long before capturing the output image.
19
+ *
20
+ * If unspecified, the default value is 5000 (5 seconds). The value zero causes the application to run indefinitely.
21
+ */
22
+ timeout: number;
8
23
  }
9
- type OptionsObject = {
10
- [key in OptionKeys]?: any;
11
- };
24
+ interface PreviewWindowOptions {
25
+ /**
26
+ * Preview window settings
27
+ *
28
+ * Sets the size and location of the preview window (both X Windows and DRM versions). It does not affect the resolution or aspect ratio of images being requested from the camera. The camera images will be scaled to the size of the preview window for display, and will be pillar/letter-boxed to fit.
29
+ *
30
+ * Example:
31
+ * ```json
32
+ * { "x": 100, "y": 100, "width": 500, "height": 500 }
33
+ * ```
34
+ */
35
+ preview: PreviewOption;
36
+ /**
37
+ * Fullscreen preview mode
38
+ *
39
+ * Forces the preview window to use the whole screen, and the window will have no border or title bar. Again the image may be pillar/letter-boxed.
40
+ */
41
+ fullscreen: boolean;
42
+ /**
43
+ * Use Qt-based preview window
44
+ *
45
+ * The preview window is switched to use the Qt-based implementation. This option is not normally recommended because it no longer uses zero-copy buffer sharing nor GPU acceleration and is therefore very expensive, however, it does support X forwarding (which the other preview implementations do not).
46
+ *
47
+ * The Qt preview window does not support the `--fullscreen` option. Generally it is advised to try and keep the preview window small.
48
+ */
49
+ 'qt-preview': boolean;
50
+ /**
51
+ * Do not display a preview window
52
+ *
53
+ * The preview window is suppressed entirely.
54
+ */
55
+ nopreview: boolean;
56
+ /**
57
+ * Set window title bar text <string>
58
+ *
59
+ * The supplied string is set as the title of the preview window (when running under X Windows). Additionally the string may contain a number of `%` directives which are substituted with information from the image metadata. The permitted directives are:
60
+ *
61
+ * | Directive | Substitution |
62
+ * | :--------------- | :------------------ |
63
+ * | `%frame` | The sequence number of the frame |
64
+ * | `%fps` | The instantaneous frame rate |
65
+ * | `%exp` | The shutter speed used to capture the image, in microseconds |
66
+ * | `%ag` | The analogue gain applied to the image in the sensor |
67
+ * | `%dg` | The digital gain applied to the image by the ISP |
68
+ * | `%rg` | The gain applied to the red component of each pixel |
69
+ * | `%bg` | The gain applied to the blue component of each pixel |
70
+ * | `%focus` | The focus metric for the image, where a larger value implies a sharper image |
71
+ *
72
+ * When not provided, the `--info-text` string defaults to `"#%frame (%fps fps) exp %exp ag %ag dg %dg"`.
73
+ */
74
+ 'info-text': string;
75
+ }
76
+ interface CameraResolutionOptions {
77
+ /**
78
+ * Capture image width <width>
79
+ *
80
+ * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.
81
+ *
82
+ * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.
83
+ *
84
+ * For libcamera-hello these parameters have no effect.
85
+ */
86
+ width: number;
87
+ /**
88
+ * Capture image height <height>
89
+ *
90
+ * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.
91
+ *
92
+ * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.
93
+ *
94
+ * For libcamera-hello these parameters have no effect.
95
+ */
96
+ height: number;
97
+ }
98
+ interface OutputFileOptions {
99
+ /**
100
+ * Output file name <string>
101
+ *
102
+ * `--output` sets the name of the output file to which the output image or video is written. Besides regular file names, this may take the following special values:
103
+ *
104
+ * `-` - write to stdout
105
+ *
106
+ * `udp://` - a string starting with this is taken as a network address for streaming
107
+ *
108
+ * `tcp://` - a string starting with this is taken as a network address for streaming
109
+ *
110
+ * a string containing a `%d` directive is taken as a file name where the format directive is replaced with a count that increments for each file that is opened. Standard C format directive modifiers are permitted.
111
+ */
112
+ output: string;
113
+ }
114
+ interface VideoOptions {
115
+ /**
116
+ * Saves timestamp information to the specified file. Useful as an input file to `mkvmerge`.
117
+ */
118
+ 'save-pts': string;
119
+ }
120
+ type OptionsObject = CommandLineOptions & PreviewWindowOptions & CameraResolutionOptions & OutputFileOptions & VideoOptions;
121
+ type OptionKeys = keyof OptionsObject;
122
+ type OptionConverter = (val: any) => string;
12
123
  interface PreviewOption {
13
124
  x: number;
14
125
  y: number;
@@ -16,5 +127,4 @@ export declare namespace LibCamera {
16
127
  height: number;
17
128
  }
18
129
  }
19
- export declare const OPTION_KEYS: readonly ["help", "version", "timeout", "preview", "fullscreen", "qt-preview", "nopreview", "info-text", "width", "height", "viewfinder-width", "viewfinder-height", "output"];
20
- export declare const OPTIONS: Record<LibCamera.OptionKeys, LibCamera.OptionDefinition>;
130
+ export declare const optionConverterMap: Partial<Record<LibCamera.OptionKeys, LibCamera.OptionConverter>>;
package/dist/utils.d.ts CHANGED
@@ -3,4 +3,4 @@ import { ExecOptionsWithBufferEncoding } from 'child_process';
3
3
  import { LibCamera } from './options';
4
4
  export declare function cmd(base: string, args?: string[]): string;
5
5
  export declare function run(command: string, options?: ExecOptionsWithBufferEncoding): Promise<unknown>;
6
- export declare function convertOptionsToCmdArgs(options: LibCamera.OptionsObject): string[];
6
+ export declare function convertOptionsToCmdArgs(options: Partial<LibCamera.OptionsObject>): string[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "node-libcamera",
3
3
  "author": "Hussain Abbas",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
7
7
  "typings": "dist/index.d.ts",
@@ -16,7 +16,7 @@
16
16
  "scripts": {
17
17
  "start": "tsdx watch",
18
18
  "build": "tsdx build",
19
- "test": "tsdx test",
19
+ "test": "tsdx test --no-cache",
20
20
  "lint": "tsdx lint",
21
21
  "prepare": "tsdx build",
22
22
  "size": "size-limit",
@@ -51,5 +51,10 @@
51
51
  "path": "dist/node-libcamera.esm.js",
52
52
  "limit": "10 KB"
53
53
  }
54
- ]
54
+ ],
55
+ "jest": {
56
+ "globals": {
57
+ "__DEV__": true
58
+ }
59
+ }
55
60
  }
package/src/index.ts CHANGED
@@ -1,8 +1,27 @@
1
1
  import { LibCamera } from './options'
2
2
  import { run, cmd, convertOptionsToCmdArgs } from './utils'
3
3
 
4
- export function snap(options: LibCamera.OptionsObject) {
4
+ function runLibCamera(
5
+ bin: string = 'libcamera-still',
6
+ options: Partial<LibCamera.OptionsObject>
7
+ ) {
5
8
  const args = convertOptionsToCmdArgs(options)
6
- const command = cmd('libcamera-still', args)
9
+ const command = cmd(bin, args)
10
+ if (__DEV__) {
11
+ console.log(command)
12
+ return command
13
+ }
7
14
  return run(command)
8
15
  }
16
+
17
+ export function jpeg(options: Partial<LibCamera.OptionsObject>) {
18
+ return runLibCamera('libcamera-jpeg', options)
19
+ }
20
+
21
+ export function still(options: Partial<LibCamera.OptionsObject>) {
22
+ return runLibCamera('libcamera-still', options)
23
+ }
24
+
25
+ export function vid(options: Partial<LibCamera.OptionsObject>) {
26
+ return runLibCamera('libcamera-vid', options)
27
+ }
package/src/options.ts CHANGED
@@ -1,17 +1,136 @@
1
1
  export namespace LibCamera {
2
- export type OptionKeys = typeof OPTION_KEYS[number]
2
+ export interface CommandLineOptions {
3
+ /**
4
+ * Print help information for the application
5
+ *
6
+ * The `--help` option causes every application to print its full set of command line options with a brief synopsis of each, and then quit.
7
+ **/
8
+ help: boolean
9
+ /**
10
+ * Print out a software version number
11
+ *
12
+ * All `libcamera-apps` will, when they see the `--version` option, print out a version string both for `libcamera` and `libcamera-apps` and then quit.
13
+ */
14
+ version: boolean
15
+ /**
16
+ * Delay before application stops automatically <milliseconds>
17
+ *
18
+ * The `--timeout` option specifies how long the application runs before it stops, whether it is recording a video or showing a preview. In the case of still image capture, the application will show the preview window for this long before capturing the output image.
19
+ *
20
+ * If unspecified, the default value is 5000 (5 seconds). The value zero causes the application to run indefinitely.
21
+ */
22
+ timeout: number
23
+ }
24
+
25
+ export interface PreviewWindowOptions {
26
+ /**
27
+ * Preview window settings
28
+ *
29
+ * Sets the size and location of the preview window (both X Windows and DRM versions). It does not affect the resolution or aspect ratio of images being requested from the camera. The camera images will be scaled to the size of the preview window for display, and will be pillar/letter-boxed to fit.
30
+ *
31
+ * Example:
32
+ * ```json
33
+ * { "x": 100, "y": 100, "width": 500, "height": 500 }
34
+ * ```
35
+ */
36
+ preview: PreviewOption
37
+ /**
38
+ * Fullscreen preview mode
39
+ *
40
+ * Forces the preview window to use the whole screen, and the window will have no border or title bar. Again the image may be pillar/letter-boxed.
41
+ */
42
+ fullscreen: boolean
43
+ /**
44
+ * Use Qt-based preview window
45
+ *
46
+ * The preview window is switched to use the Qt-based implementation. This option is not normally recommended because it no longer uses zero-copy buffer sharing nor GPU acceleration and is therefore very expensive, however, it does support X forwarding (which the other preview implementations do not).
47
+ *
48
+ * The Qt preview window does not support the `--fullscreen` option. Generally it is advised to try and keep the preview window small.
49
+ */
50
+ 'qt-preview': boolean
51
+ /**
52
+ * Do not display a preview window
53
+ *
54
+ * The preview window is suppressed entirely.
55
+ */
56
+ nopreview: boolean
57
+ /**
58
+ * Set window title bar text <string>
59
+ *
60
+ * The supplied string is set as the title of the preview window (when running under X Windows). Additionally the string may contain a number of `%` directives which are substituted with information from the image metadata. The permitted directives are:
61
+ *
62
+ * | Directive | Substitution |
63
+ * | :--------------- | :------------------ |
64
+ * | `%frame` | The sequence number of the frame |
65
+ * | `%fps` | The instantaneous frame rate |
66
+ * | `%exp` | The shutter speed used to capture the image, in microseconds |
67
+ * | `%ag` | The analogue gain applied to the image in the sensor |
68
+ * | `%dg` | The digital gain applied to the image by the ISP |
69
+ * | `%rg` | The gain applied to the red component of each pixel |
70
+ * | `%bg` | The gain applied to the blue component of each pixel |
71
+ * | `%focus` | The focus metric for the image, where a larger value implies a sharper image |
72
+ *
73
+ * When not provided, the `--info-text` string defaults to `"#%frame (%fps fps) exp %exp ag %ag dg %dg"`.
74
+ */
75
+ 'info-text': string
76
+ }
77
+
78
+ export interface CameraResolutionOptions {
79
+ /**
80
+ * Capture image width <width>
81
+ *
82
+ * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.
83
+ *
84
+ * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.
85
+ *
86
+ * For libcamera-hello these parameters have no effect.
87
+ */
88
+ width: number
89
+ /**
90
+ * Capture image height <height>
91
+ *
92
+ * This number specifies the output resolution of the camera images captured by libcamera-still, libcamera-jpeg and libcamera-vid.
93
+ *
94
+ * For libcamera-raw, it affects the size of the raw frames captured. Where a camera has a 2x2 binned readout mode, specifying a resolution not larger than this binned mode will result in the capture of 2x2 binned raw frames.
95
+ *
96
+ * For libcamera-hello these parameters have no effect.
97
+ */
98
+ height: number
99
+ }
3
100
 
4
- export interface OptionDefinition {
5
- short?: string
6
- desc?: string
7
- validator?: (val: any) => boolean
8
- convert?: (val: any) => string
101
+ export interface OutputFileOptions {
102
+ /**
103
+ * Output file name <string>
104
+ *
105
+ * `--output` sets the name of the output file to which the output image or video is written. Besides regular file names, this may take the following special values:
106
+ *
107
+ * `-` - write to stdout
108
+ *
109
+ * `udp://` - a string starting with this is taken as a network address for streaming
110
+ *
111
+ * `tcp://` - a string starting with this is taken as a network address for streaming
112
+ *
113
+ * a string containing a `%d` directive is taken as a file name where the format directive is replaced with a count that increments for each file that is opened. Standard C format directive modifiers are permitted.
114
+ */
115
+ output: string
9
116
  }
10
117
 
11
- export type OptionsObject = {
12
- [key in OptionKeys]?: any
118
+ export interface VideoOptions {
119
+ /**
120
+ * Saves timestamp information to the specified file. Useful as an input file to `mkvmerge`.
121
+ */
122
+ 'save-pts': string
13
123
  }
14
124
 
125
+ export type OptionsObject = CommandLineOptions &
126
+ PreviewWindowOptions &
127
+ CameraResolutionOptions &
128
+ OutputFileOptions &
129
+ VideoOptions
130
+
131
+ export type OptionKeys = keyof OptionsObject
132
+ export type OptionConverter = (val: any) => string
133
+
15
134
  export interface PreviewOption {
16
135
  x: number
17
136
  y: number
@@ -20,94 +139,11 @@ export namespace LibCamera {
20
139
  }
21
140
  }
22
141
 
23
- export const OPTION_KEYS = [
24
- 'help',
25
- 'version',
26
- 'timeout',
27
- 'preview',
28
- 'fullscreen',
29
- 'qt-preview',
30
- 'nopreview',
31
- 'info-text',
32
- 'width',
33
- 'height',
34
- 'viewfinder-width',
35
- 'viewfinder-height',
36
- // ...
37
- 'output',
38
- ] as const
39
-
40
- export const OPTIONS: Record<
142
+ export const optionConverterMap: Partial<Record<
41
143
  LibCamera.OptionKeys,
42
- LibCamera.OptionDefinition
43
- > = {
44
- help: {
45
- short: 'h',
46
- desc: 'Print help information for the application',
47
- },
48
- version: {
49
- desc: 'Print help information for the application',
50
- },
51
- timeout: {
52
- short: 't',
53
- desc: 'Delay before application stops automatically <milliseconds>',
54
- validator: (val: number) => typeof val === 'number',
55
- convert: (val: number) => val.toString(),
56
- },
57
- preview: {
58
- short: 'p',
59
- desc: 'Preview window settings <x,y,w,h>',
60
- validator(val: LibCamera.PreviewOption) {
61
- return (
62
- typeof val === 'object' &&
63
- Boolean(val?.x && val?.y && val?.width && val?.height)
64
- )
65
- },
66
- convert(val: LibCamera.PreviewOption) {
67
- return `${val.x},${val.y},${val.width},${val.height}`
68
- },
69
- },
70
- fullscreen: {
71
- short: 'f',
72
- desc: 'Fullscreen preview mode',
73
- },
74
- 'qt-preview': {
75
- desc: 'Use Qt-based preview window',
76
- },
77
- nopreview: {
78
- short: 'n',
79
- desc: 'Do not display a preview window',
80
- },
81
- 'info-text': {
82
- desc: 'Set window title bar text <string>',
83
- validator: (val: string) => typeof val === 'string',
84
- },
85
- width: {
86
- desc: 'Capture image width <width>',
87
- validator: (val: number) => typeof val === 'number',
88
- convert: (val: number) => val.toString(),
89
- },
90
- height: {
91
- desc: 'Capture image height <height>',
92
- validator: (val: number) => typeof val === 'number',
93
- convert: (val: number) => val.toString(),
94
- },
95
- 'viewfinder-width': {
96
- desc: 'Capture image width <width>',
97
- validator: (val: number) => typeof val === 'number',
98
- convert: (val: number) => val.toString(),
99
- },
100
- 'viewfinder-height': {
101
- desc: 'Capture image height <height>',
102
- validator: (val: number) => typeof val === 'number',
103
- convert: (val: number) => val.toString(),
104
- },
105
-
106
- // ...
107
-
108
- output: {
109
- short: 'o',
110
- desc: 'Output file name <string>',
111
- validator: (val: string) => typeof val === 'string',
144
+ LibCamera.OptionConverter
145
+ >> = {
146
+ preview(val: LibCamera.PreviewOption) {
147
+ return `${val.x},${val.y},${val.width},${val.height}`
112
148
  },
113
149
  } as const
package/src/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { exec, ExecOptionsWithBufferEncoding } from 'child_process'
2
- import { OPTIONS, LibCamera } from './options'
2
+ import { optionConverterMap, LibCamera } from './options'
3
3
 
4
4
  export function cmd(base: string, args?: string[]): string {
5
5
  if (base && !args) return base
@@ -16,17 +16,14 @@ export function run(command: string, options?: ExecOptionsWithBufferEncoding) {
16
16
  }
17
17
 
18
18
  export function convertOptionsToCmdArgs(
19
- options: LibCamera.OptionsObject
19
+ options: Partial<LibCamera.OptionsObject>
20
20
  ): string[] {
21
21
  const args: string[] = []
22
22
  Object.entries(options).forEach(([key, val]) => {
23
- const opt = OPTIONS[key as LibCamera.OptionKeys]
24
- if (typeof opt.validator === 'function' && !opt.validator(val)) {
25
- throw new Error(`Invalid value for option "${key}"`)
26
- }
27
- const value = typeof opt.convert === 'function' ? opt.convert(val) : val
23
+ const converter = optionConverterMap[key as LibCamera.OptionKeys]
24
+ const value = typeof converter === 'function' ? converter(val) : val
28
25
  if (value) args.push(`--${key}`)
29
- if (value !== true) args.push(value)
26
+ if (value !== true && value?.toString()) args.push(value?.toString())
30
27
  }, true)
31
28
  return args
32
29
  }