nokhwa-node 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +266 -0
- package/browser.js +1 -0
- package/index.d.ts +196 -0
- package/index.js +595 -0
- package/package.json +129 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 N-API for Rust
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# nokhwa-node
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Node.js bindings for [nokhwa](https://github.com/l1npengtul/nokhwa) camera library using [napi-rs](https://napi.rs/). This package provides native performance for camera access across multiple platforms including WebAssembly via WASI.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Cross-platform support**: macOS, Linux (glibc & musl), Windows, FreeBSD, and WebAssembly (WASI)
|
|
10
|
+
- **High performance**: Native Rust implementation with N-API for optimal speed
|
|
11
|
+
- **WebAssembly support**: Run camera operations in browser and edge environments via WASI
|
|
12
|
+
- **Thread-safe**: Multi-threaded camera access support
|
|
13
|
+
- **Easy to use**: Simple JavaScript/TypeScript API
|
|
14
|
+
|
|
15
|
+
## Supported Platforms
|
|
16
|
+
|
|
17
|
+
| Platform | Architecture | Status |
|
|
18
|
+
|----------|-------------|--------|
|
|
19
|
+
| macOS | x86_64, ARM64 (Apple Silicon) | ✅ |
|
|
20
|
+
| Windows | x86_64, i686, ARM64 | ✅ |
|
|
21
|
+
| Linux | x86_64, aarch64 (glibc & musl) | ✅ |
|
|
22
|
+
| FreeBSD | x86_64 | ✅ |
|
|
23
|
+
| WebAssembly | wasm32-wasip1-threads | ✅ |
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install nokhwa-node
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { Camera, CameraFormat } from 'nokhwa-node';
|
|
35
|
+
|
|
36
|
+
// List available cameras
|
|
37
|
+
const cameras = await Camera.list_cameras();
|
|
38
|
+
console.log('Available cameras:', cameras);
|
|
39
|
+
|
|
40
|
+
// Open a camera
|
|
41
|
+
const camera = new Camera(0, {
|
|
42
|
+
width: 640,
|
|
43
|
+
height: 480,
|
|
44
|
+
format: 'mjpeg',
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Start the camera stream
|
|
48
|
+
await camera.open_stream();
|
|
49
|
+
|
|
50
|
+
// Capture a frame
|
|
51
|
+
const frame = await camera.frame();
|
|
52
|
+
console.log('Frame size:', frame.len);
|
|
53
|
+
|
|
54
|
+
// Close the camera
|
|
55
|
+
camera.stop();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Building Locally
|
|
59
|
+
|
|
60
|
+
### Prerequisites
|
|
61
|
+
|
|
62
|
+
- **Rust**: Latest stable version
|
|
63
|
+
- **Node.js**: >= 10 (NAPI support)
|
|
64
|
+
- **Yarn**: 1.x or higher
|
|
65
|
+
|
|
66
|
+
### Standard Build
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Install dependencies
|
|
70
|
+
yarn install
|
|
71
|
+
|
|
72
|
+
# Build for current platform
|
|
73
|
+
yarn build
|
|
74
|
+
|
|
75
|
+
# Run tests
|
|
76
|
+
yarn test
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Building for WebAssembly (WASI)
|
|
80
|
+
|
|
81
|
+
To build for the `wasm32-wasip1-threads` target locally, you need to install the WASI SDK and configure your build environment:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Download and extract WASI SDK
|
|
85
|
+
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-22/wasi-sdk-22.0-linux.tar.gz
|
|
86
|
+
tar xvf wasi-sdk-22.0-linux.tar.gz
|
|
87
|
+
|
|
88
|
+
# Set environment variables
|
|
89
|
+
export WASI_SDK_PATH="$(pwd)/wasi-sdk-22.0"
|
|
90
|
+
export CC="${WASI_SDK_PATH}/bin/clang"
|
|
91
|
+
export AR="${WASI_SDK_PATH}/bin/llvm-ar"
|
|
92
|
+
export CFLAGS="--sysroot=${WASI_SDK_PATH}/share/wasi-sysroot"
|
|
93
|
+
|
|
94
|
+
# Build for WASI target
|
|
95
|
+
yarn build --platform --target wasm32-wasip1-threads
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Building for Specific Platforms
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Build for all supported platforms
|
|
102
|
+
yarn build --platform
|
|
103
|
+
|
|
104
|
+
# Build for a specific target
|
|
105
|
+
yarn build --platform --target x86_64-unknown-linux-gnu
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## CI/CD Pipeline
|
|
109
|
+
|
|
110
|
+
This project uses GitHub Actions for continuous integration and automated releases. The CI pipeline builds and tests across all supported platforms:
|
|
111
|
+
|
|
112
|
+
### Build Matrix
|
|
113
|
+
|
|
114
|
+
- **Node.js versions**: 20, 22
|
|
115
|
+
- **Platforms**:
|
|
116
|
+
- macOS (x86_64, ARM64)
|
|
117
|
+
- Windows (x86_64, i686, ARM64)
|
|
118
|
+
- Linux (x86_64, aarch64 with glibc & musl)
|
|
119
|
+
- FreeBSD (x86_64)
|
|
120
|
+
- WebAssembly (wasm32-wasip1-threads)
|
|
121
|
+
|
|
122
|
+
### WASI Build Configuration
|
|
123
|
+
|
|
124
|
+
The WebAssembly build requires special handling to ensure all necessary libc headers are available. The CI workflow automatically:
|
|
125
|
+
|
|
126
|
+
1. **Installs WASI SDK** - Downloads wasi-sdk-22.0 for the wasm target
|
|
127
|
+
2. **Configures environment variables**:
|
|
128
|
+
- `CC`: Points to WASI SDK's clang compiler
|
|
129
|
+
- `AR`: Points to WASI SDK's llvm-ar
|
|
130
|
+
- `CFLAGS`: Sets `--sysroot` to the WASI sysroot
|
|
131
|
+
3. **Builds with proper toolchain** - Ensures clang can find libc headers like `bits/libc-header-start.h`
|
|
132
|
+
|
|
133
|
+
### Testing
|
|
134
|
+
|
|
135
|
+
All builds are automatically tested using [AVA](https://avajs.dev/) across different Node.js versions to ensure compatibility and correctness.
|
|
136
|
+
|
|
137
|
+
## Development
|
|
138
|
+
|
|
139
|
+
### Running Benchmarks
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Build and run benchmarks
|
|
143
|
+
yarn bench
|
|
144
|
+
|
|
145
|
+
# Build in debug mode and run benchmarks
|
|
146
|
+
yarn bench:debug
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Code Formatting
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Format all code (JavaScript, TypeScript, Rust, TOML)
|
|
153
|
+
yarn format
|
|
154
|
+
|
|
155
|
+
# Format individual parts
|
|
156
|
+
yarn format:prettier # JS/TS/YAML/MD/JSON
|
|
157
|
+
yarn format:rs # Rust
|
|
158
|
+
yarn format:toml # TOML
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Linting
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Run linter
|
|
165
|
+
yarn lint
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Release Process
|
|
169
|
+
|
|
170
|
+
The release process is automated via GitHub Actions:
|
|
171
|
+
|
|
172
|
+
1. Update version using semantic versioning:
|
|
173
|
+
```bash
|
|
174
|
+
npm version [major | minor | patch]
|
|
175
|
+
```
|
|
176
|
+
2. Push to trigger the release workflow:
|
|
177
|
+
```bash
|
|
178
|
+
git push
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The CI pipeline will:
|
|
182
|
+
- Build binaries for all supported platforms
|
|
183
|
+
- Run tests across all platforms and Node.js versions
|
|
184
|
+
- Publish platform-specific packages to npm
|
|
185
|
+
- Publish the main package with optional dependencies
|
|
186
|
+
|
|
187
|
+
### Platform-Specific Packages
|
|
188
|
+
|
|
189
|
+
For optimal user experience, this package publishes separate npm packages for each platform:
|
|
190
|
+
|
|
191
|
+
- `@nokhwa/node-darwin-x64`
|
|
192
|
+
- `@nokhwa/node-darwin-arm64`
|
|
193
|
+
- `@nokhwa/node-win32-x64`
|
|
194
|
+
- `@nokhwa/node-win32-ia32`
|
|
195
|
+
- `@nokhwa/node-win32-arm64`
|
|
196
|
+
- `@nokhwa/node-linux-x64-gnu`
|
|
197
|
+
- `@nokhwa/node-linux-x64-musl`
|
|
198
|
+
- `@nokhwa/node-linux-arm64-gnu`
|
|
199
|
+
- `@nokhwa/node-linux-arm64-musl`
|
|
200
|
+
- `@nokhwa/node-freebsd-x64`
|
|
201
|
+
- `@nokhwa/node-wasm32-wasi`
|
|
202
|
+
|
|
203
|
+
NPM automatically selects the correct package for the user's platform, eliminating the need for users to install build toolchains or download binaries manually.
|
|
204
|
+
|
|
205
|
+
### Setup for Release
|
|
206
|
+
|
|
207
|
+
Ensure you've added your `NPM_TOKEN` in GitHub repository settings:
|
|
208
|
+
|
|
209
|
+
1. Go to **Settings → Secrets and variables → Actions**
|
|
210
|
+
2. Add a new secret named `NPM_TOKEN` with your npm authentication token
|
|
211
|
+
|
|
212
|
+
⚠️ **Important**: Do not run `npm publish` manually. Use the automated release workflow instead.
|
|
213
|
+
|
|
214
|
+
## Troubleshooting
|
|
215
|
+
|
|
216
|
+
### WASI Build Failures
|
|
217
|
+
|
|
218
|
+
If you encounter errors like `bits/libc-header-start.h: No such file or directory` when building for WebAssembly:
|
|
219
|
+
|
|
220
|
+
1. Ensure WASI SDK is properly installed
|
|
221
|
+
2. Verify the `WASI_SYSROOT` environment variable is set correctly
|
|
222
|
+
3. Check that `CC` and `AR` point to the WASI SDK tools
|
|
223
|
+
4. Make sure `CFLAGS` includes the `--sysroot` flag
|
|
224
|
+
|
|
225
|
+
Example:
|
|
226
|
+
```bash
|
|
227
|
+
export WASI_SYSROOT="/path/to/wasi-sdk-22.0/share/wasi-sysroot"
|
|
228
|
+
export CC="/path/to/wasi-sdk-22.0/bin/clang"
|
|
229
|
+
export AR="/path/to/wasi-sdk-22.0/bin/llvm-ar"
|
|
230
|
+
export CFLAGS="--sysroot=$WASI_SYSROOT"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Platform-Specific Issues
|
|
234
|
+
|
|
235
|
+
For platform-specific build issues, ensure you have the required toolchain:
|
|
236
|
+
|
|
237
|
+
- **macOS**: Xcode Command Line Tools
|
|
238
|
+
- **Linux**: `gcc`, `glibc-devel` (or `musl-dev` for musl builds)
|
|
239
|
+
- **Windows**: Visual Studio Build Tools or MSVC
|
|
240
|
+
- **FreeBSD**: Build environment with proper development tools
|
|
241
|
+
|
|
242
|
+
## Contributing
|
|
243
|
+
|
|
244
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
245
|
+
|
|
246
|
+
1. Fork the repository
|
|
247
|
+
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
|
248
|
+
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
249
|
+
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
250
|
+
5. Open a Pull Request
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
255
|
+
|
|
256
|
+
## Acknowledgments
|
|
257
|
+
|
|
258
|
+
- [nokhwa](https://github.com/l1npengtul/nokhwa) - The underlying Rust camera library
|
|
259
|
+
- [napi-rs](https://napi.rs/) - Framework for building Node.js native modules in Rust
|
|
260
|
+
- [WASI SDK](https://github.com/WebAssembly/wasi-sdk) - WebAssembly System Interface toolchain
|
|
261
|
+
|
|
262
|
+
## Links
|
|
263
|
+
|
|
264
|
+
- [GitHub Repository](https://github.com/nglmercer/nokhwa-node)
|
|
265
|
+
- [NPM Package](https://www.npmjs.com/package/nokhwa-node)
|
|
266
|
+
- [Documentation](https://github.com/nglmercer/nokhwa-node#readme)
|
package/browser.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from 'nokhwa-node-wasm32-wasi'
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/* auto-generated by NAPI-RS */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/** Camera instance for capturing frames with full nokhwa functionality */
|
|
4
|
+
export declare class Camera {
|
|
5
|
+
/**
|
|
6
|
+
* Create a new camera instance with the given index
|
|
7
|
+
* The camera stream is opened immediately with automatic format detection
|
|
8
|
+
*/
|
|
9
|
+
constructor(cameraIndex: string)
|
|
10
|
+
/**
|
|
11
|
+
* Capture a single frame from the camera
|
|
12
|
+
* Returns the frame as RGBA buffer with width and height
|
|
13
|
+
*/
|
|
14
|
+
captureFrame(): Frame
|
|
15
|
+
/** Get the camera index */
|
|
16
|
+
index(): string
|
|
17
|
+
/** Get the backend being used */
|
|
18
|
+
backend(): ApiBackend
|
|
19
|
+
/** Get camera information */
|
|
20
|
+
info(): CameraDevice
|
|
21
|
+
/** Get the current camera format */
|
|
22
|
+
cameraFormat(): CameraFormat
|
|
23
|
+
/** Refresh and get the camera format */
|
|
24
|
+
refreshCameraFormat(): CameraFormat
|
|
25
|
+
/** Set camera format with requested configuration */
|
|
26
|
+
setCameraRequest(request: RequestedFormatConfig): CameraFormat
|
|
27
|
+
/** Get compatible camera formats */
|
|
28
|
+
compatibleCameraFormats(): Array<CameraFormat>
|
|
29
|
+
/** Get supported camera controls */
|
|
30
|
+
supportedCameraControls(): Array<KnownCameraControl>
|
|
31
|
+
/** Get all camera controls */
|
|
32
|
+
cameraControls(): Array<CameraControl>
|
|
33
|
+
/** Set a camera control value */
|
|
34
|
+
setCameraControl(control: KnownCameraControl, value: ControlValueSetter): void
|
|
35
|
+
/** Check if stream is open */
|
|
36
|
+
isStreamOpen(): boolean
|
|
37
|
+
/** Open the camera stream */
|
|
38
|
+
openStream(): void
|
|
39
|
+
/** Stop the camera stream */
|
|
40
|
+
stopStream(): void
|
|
41
|
+
/** Get raw frame data */
|
|
42
|
+
frameRaw(): CameraBuffer
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Buffer struct representing raw camera frame data */
|
|
46
|
+
export declare class CameraBuffer {
|
|
47
|
+
/** Create a new buffer with resolution, data, and format */
|
|
48
|
+
constructor(resolution: Resolution, data: Buffer, sourceFrameFormat: FrameFormat)
|
|
49
|
+
/** Get the resolution of the buffer */
|
|
50
|
+
resolution(): Resolution
|
|
51
|
+
/** Get the raw buffer data */
|
|
52
|
+
data(): Buffer
|
|
53
|
+
/** Get the source frame format */
|
|
54
|
+
sourceFrameFormat(): FrameFormat
|
|
55
|
+
/** Get the width of the buffer */
|
|
56
|
+
width(): number
|
|
57
|
+
/** Get the height of the buffer */
|
|
58
|
+
height(): number
|
|
59
|
+
/** Get the size of the buffer in bytes */
|
|
60
|
+
size(): number
|
|
61
|
+
/** Check if the buffer is empty */
|
|
62
|
+
isEmpty(): boolean
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Get all known camera controls */
|
|
66
|
+
export declare function allKnownCameraControls(): Array<KnownCameraControl>
|
|
67
|
+
|
|
68
|
+
/** API backend options for camera access */
|
|
69
|
+
export declare const enum ApiBackend {
|
|
70
|
+
Auto = 'Auto',
|
|
71
|
+
MediaFoundation = 'MediaFoundation',
|
|
72
|
+
AVFoundation = 'AVFoundation',
|
|
73
|
+
OpenCv = 'OpenCv',
|
|
74
|
+
Browser = 'Browser'
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Convert BGR buffer to RGB */
|
|
78
|
+
export declare function bufBgrToRgb(width: number, height: number, bgr: Buffer): Buffer
|
|
79
|
+
|
|
80
|
+
/** Convert MJPEG buffer to RGB */
|
|
81
|
+
export declare function bufMjpegToRgb(width: number, height: number, mjpeg: Buffer): Buffer
|
|
82
|
+
|
|
83
|
+
/** Convert NV12 buffer to RGB */
|
|
84
|
+
export declare function bufNv12ToRgb(width: number, height: number, nv12: Buffer): Buffer
|
|
85
|
+
|
|
86
|
+
/** Convert YUYV422 buffer to RGB */
|
|
87
|
+
export declare function bufYuyv422ToRgb(width: number, height: number, yuyv: Buffer): Buffer
|
|
88
|
+
|
|
89
|
+
/** Camera control descriptor */
|
|
90
|
+
export interface CameraControl {
|
|
91
|
+
name: string
|
|
92
|
+
controlType: string
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Camera device information */
|
|
96
|
+
export interface CameraDevice {
|
|
97
|
+
index: string
|
|
98
|
+
name: string
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Camera format specification */
|
|
102
|
+
export interface CameraFormat {
|
|
103
|
+
resolution: Resolution
|
|
104
|
+
frameRate: number
|
|
105
|
+
format: FrameFormat
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Get all color frame formats */
|
|
109
|
+
export declare function colorFrameFormats(): Array<FrameFormat>
|
|
110
|
+
|
|
111
|
+
/** Control value types for setting camera properties */
|
|
112
|
+
export type ControlValueSetter =
|
|
113
|
+
| { type: 'Integer', field0: number }
|
|
114
|
+
| { type: 'Float', field0: number }
|
|
115
|
+
| { type: 'Boolean', field0: boolean }
|
|
116
|
+
| { type: 'String', field0: string }
|
|
117
|
+
|
|
118
|
+
/** Frame structure exported to JavaScript/TypeScript */
|
|
119
|
+
export interface Frame {
|
|
120
|
+
data: Buffer
|
|
121
|
+
width: number
|
|
122
|
+
height: number
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Frame format types supported by the camera */
|
|
126
|
+
export declare const enum FrameFormat {
|
|
127
|
+
MJPEG = 'MJPEG',
|
|
128
|
+
YUYV = 'YUYV',
|
|
129
|
+
NV12 = 'NV12',
|
|
130
|
+
RGB = 'RGB',
|
|
131
|
+
RGBA = 'RGBA',
|
|
132
|
+
GRAY = 'GRAY'
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Get all available frame formats */
|
|
136
|
+
export declare function frameFormats(): Array<FrameFormat>
|
|
137
|
+
|
|
138
|
+
/** Known camera control properties */
|
|
139
|
+
export declare const enum KnownCameraControl {
|
|
140
|
+
Brightness = 'Brightness',
|
|
141
|
+
Contrast = 'Contrast',
|
|
142
|
+
Saturation = 'Saturation',
|
|
143
|
+
Hue = 'Hue',
|
|
144
|
+
WhiteBalance = 'WhiteBalance',
|
|
145
|
+
Gamma = 'Gamma',
|
|
146
|
+
Sharpness = 'Sharpness',
|
|
147
|
+
BacklightComp = 'BacklightComp',
|
|
148
|
+
Gain = 'Gain',
|
|
149
|
+
Pan = 'Pan',
|
|
150
|
+
Tilt = 'Tilt',
|
|
151
|
+
Zoom = 'Zoom',
|
|
152
|
+
Exposure = 'Exposure',
|
|
153
|
+
Iris = 'Iris',
|
|
154
|
+
Focus = 'Focus'
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** List all available cameras */
|
|
158
|
+
export declare function listCameras(): Array<CameraDevice>
|
|
159
|
+
|
|
160
|
+
/** Convert MJPEG to RGB (convenience function) */
|
|
161
|
+
export declare function mjpegToRgb(mjpeg: Buffer, width: number, height: number): Buffer
|
|
162
|
+
|
|
163
|
+
/** Get native API backend */
|
|
164
|
+
export declare function nativeApiBackend(): ApiBackend | null
|
|
165
|
+
|
|
166
|
+
/** Check if nokhwa is initialized */
|
|
167
|
+
export declare function nokhwaCheck(): boolean
|
|
168
|
+
|
|
169
|
+
/** Convert NV12 to RGB (convenience function) */
|
|
170
|
+
export declare function nv12ToRgb(nv12: Buffer, width: number, height: number): Buffer
|
|
171
|
+
|
|
172
|
+
/** Query available cameras with specific backend */
|
|
173
|
+
export declare function query(backend: ApiBackend): Array<CameraDevice>
|
|
174
|
+
|
|
175
|
+
/** Requested format configuration */
|
|
176
|
+
export interface RequestedFormatConfig {
|
|
177
|
+
requestType: RequestedFormatType
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Format request types for automatic format selection */
|
|
181
|
+
export declare const enum RequestedFormatType {
|
|
182
|
+
AbsoluteHighestResolution = 'AbsoluteHighestResolution',
|
|
183
|
+
AbsoluteHighestFrameRate = 'AbsoluteHighestFrameRate'
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Resolution dimensions */
|
|
187
|
+
export interface Resolution {
|
|
188
|
+
width: number
|
|
189
|
+
height: number
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Get predicted size for YUYV422 format */
|
|
193
|
+
export declare function yuyv422PredictedSize(width: number, height: number): number
|
|
194
|
+
|
|
195
|
+
/** Convert YUYV422 to RGB (convenience function) */
|
|
196
|
+
export declare function yuyv422ToRgb(yuyv: Buffer, width: number, height: number): Buffer
|
package/index.js
ADDED
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
// prettier-ignore
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
const { readFileSync } = require('node:fs')
|
|
7
|
+
let nativeBinding = null
|
|
8
|
+
const loadErrors = []
|
|
9
|
+
|
|
10
|
+
const isMusl = () => {
|
|
11
|
+
let musl = false
|
|
12
|
+
if (process.platform === 'linux') {
|
|
13
|
+
musl = isMuslFromFilesystem()
|
|
14
|
+
if (musl === null) {
|
|
15
|
+
musl = isMuslFromReport()
|
|
16
|
+
}
|
|
17
|
+
if (musl === null) {
|
|
18
|
+
musl = isMuslFromChildProcess()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return musl
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-')
|
|
25
|
+
|
|
26
|
+
const isMuslFromFilesystem = () => {
|
|
27
|
+
try {
|
|
28
|
+
return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl')
|
|
29
|
+
} catch {
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const isMuslFromReport = () => {
|
|
35
|
+
let report = null
|
|
36
|
+
if (typeof process.report?.getReport === 'function') {
|
|
37
|
+
process.report.excludeNetwork = true
|
|
38
|
+
report = process.report.getReport()
|
|
39
|
+
}
|
|
40
|
+
if (!report) {
|
|
41
|
+
return null
|
|
42
|
+
}
|
|
43
|
+
if (report.header && report.header.glibcVersionRuntime) {
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(report.sharedObjects)) {
|
|
47
|
+
if (report.sharedObjects.some(isFileMusl)) {
|
|
48
|
+
return true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const isMuslFromChildProcess = () => {
|
|
55
|
+
try {
|
|
56
|
+
return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl')
|
|
57
|
+
} catch (e) {
|
|
58
|
+
// If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function requireNative() {
|
|
64
|
+
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
|
|
65
|
+
try {
|
|
66
|
+
return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
loadErrors.push(err)
|
|
69
|
+
}
|
|
70
|
+
} else if (process.platform === 'android') {
|
|
71
|
+
if (process.arch === 'arm64') {
|
|
72
|
+
try {
|
|
73
|
+
return require('./nokhwa-node.android-arm64.node')
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadErrors.push(e)
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const binding = require('nokhwa-node-android-arm64')
|
|
79
|
+
const bindingPackageVersion = require('nokhwa-node-android-arm64/package.json').version
|
|
80
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
81
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
82
|
+
}
|
|
83
|
+
return binding
|
|
84
|
+
} catch (e) {
|
|
85
|
+
loadErrors.push(e)
|
|
86
|
+
}
|
|
87
|
+
} else if (process.arch === 'arm') {
|
|
88
|
+
try {
|
|
89
|
+
return require('./nokhwa-node.android-arm-eabi.node')
|
|
90
|
+
} catch (e) {
|
|
91
|
+
loadErrors.push(e)
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const binding = require('nokhwa-node-android-arm-eabi')
|
|
95
|
+
const bindingPackageVersion = require('nokhwa-node-android-arm-eabi/package.json').version
|
|
96
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
97
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
98
|
+
}
|
|
99
|
+
return binding
|
|
100
|
+
} catch (e) {
|
|
101
|
+
loadErrors.push(e)
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`))
|
|
105
|
+
}
|
|
106
|
+
} else if (process.platform === 'win32') {
|
|
107
|
+
if (process.arch === 'x64') {
|
|
108
|
+
if (process.config?.variables?.shlib_suffix === 'dll.a' || process.config?.variables?.node_target_type === 'shared_library') {
|
|
109
|
+
try {
|
|
110
|
+
return require('./nokhwa-node.win32-x64-gnu.node')
|
|
111
|
+
} catch (e) {
|
|
112
|
+
loadErrors.push(e)
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const binding = require('nokhwa-node-win32-x64-gnu')
|
|
116
|
+
const bindingPackageVersion = require('nokhwa-node-win32-x64-gnu/package.json').version
|
|
117
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
118
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
119
|
+
}
|
|
120
|
+
return binding
|
|
121
|
+
} catch (e) {
|
|
122
|
+
loadErrors.push(e)
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
try {
|
|
126
|
+
return require('./nokhwa-node.win32-x64-msvc.node')
|
|
127
|
+
} catch (e) {
|
|
128
|
+
loadErrors.push(e)
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const binding = require('nokhwa-node-win32-x64-msvc')
|
|
132
|
+
const bindingPackageVersion = require('nokhwa-node-win32-x64-msvc/package.json').version
|
|
133
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
134
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
135
|
+
}
|
|
136
|
+
return binding
|
|
137
|
+
} catch (e) {
|
|
138
|
+
loadErrors.push(e)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} else if (process.arch === 'ia32') {
|
|
142
|
+
try {
|
|
143
|
+
return require('./nokhwa-node.win32-ia32-msvc.node')
|
|
144
|
+
} catch (e) {
|
|
145
|
+
loadErrors.push(e)
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const binding = require('nokhwa-node-win32-ia32-msvc')
|
|
149
|
+
const bindingPackageVersion = require('nokhwa-node-win32-ia32-msvc/package.json').version
|
|
150
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
151
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
152
|
+
}
|
|
153
|
+
return binding
|
|
154
|
+
} catch (e) {
|
|
155
|
+
loadErrors.push(e)
|
|
156
|
+
}
|
|
157
|
+
} else if (process.arch === 'arm64') {
|
|
158
|
+
try {
|
|
159
|
+
return require('./nokhwa-node.win32-arm64-msvc.node')
|
|
160
|
+
} catch (e) {
|
|
161
|
+
loadErrors.push(e)
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
const binding = require('nokhwa-node-win32-arm64-msvc')
|
|
165
|
+
const bindingPackageVersion = require('nokhwa-node-win32-arm64-msvc/package.json').version
|
|
166
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
167
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
168
|
+
}
|
|
169
|
+
return binding
|
|
170
|
+
} catch (e) {
|
|
171
|
+
loadErrors.push(e)
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`))
|
|
175
|
+
}
|
|
176
|
+
} else if (process.platform === 'darwin') {
|
|
177
|
+
try {
|
|
178
|
+
return require('./nokhwa-node.darwin-universal.node')
|
|
179
|
+
} catch (e) {
|
|
180
|
+
loadErrors.push(e)
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
const binding = require('nokhwa-node-darwin-universal')
|
|
184
|
+
const bindingPackageVersion = require('nokhwa-node-darwin-universal/package.json').version
|
|
185
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
186
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
187
|
+
}
|
|
188
|
+
return binding
|
|
189
|
+
} catch (e) {
|
|
190
|
+
loadErrors.push(e)
|
|
191
|
+
}
|
|
192
|
+
if (process.arch === 'x64') {
|
|
193
|
+
try {
|
|
194
|
+
return require('./nokhwa-node.darwin-x64.node')
|
|
195
|
+
} catch (e) {
|
|
196
|
+
loadErrors.push(e)
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
const binding = require('nokhwa-node-darwin-x64')
|
|
200
|
+
const bindingPackageVersion = require('nokhwa-node-darwin-x64/package.json').version
|
|
201
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
202
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
203
|
+
}
|
|
204
|
+
return binding
|
|
205
|
+
} catch (e) {
|
|
206
|
+
loadErrors.push(e)
|
|
207
|
+
}
|
|
208
|
+
} else if (process.arch === 'arm64') {
|
|
209
|
+
try {
|
|
210
|
+
return require('./nokhwa-node.darwin-arm64.node')
|
|
211
|
+
} catch (e) {
|
|
212
|
+
loadErrors.push(e)
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const binding = require('nokhwa-node-darwin-arm64')
|
|
216
|
+
const bindingPackageVersion = require('nokhwa-node-darwin-arm64/package.json').version
|
|
217
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
218
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
219
|
+
}
|
|
220
|
+
return binding
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loadErrors.push(e)
|
|
223
|
+
}
|
|
224
|
+
} else {
|
|
225
|
+
loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`))
|
|
226
|
+
}
|
|
227
|
+
} else if (process.platform === 'freebsd') {
|
|
228
|
+
if (process.arch === 'x64') {
|
|
229
|
+
try {
|
|
230
|
+
return require('./nokhwa-node.freebsd-x64.node')
|
|
231
|
+
} catch (e) {
|
|
232
|
+
loadErrors.push(e)
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
const binding = require('nokhwa-node-freebsd-x64')
|
|
236
|
+
const bindingPackageVersion = require('nokhwa-node-freebsd-x64/package.json').version
|
|
237
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
238
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
239
|
+
}
|
|
240
|
+
return binding
|
|
241
|
+
} catch (e) {
|
|
242
|
+
loadErrors.push(e)
|
|
243
|
+
}
|
|
244
|
+
} else if (process.arch === 'arm64') {
|
|
245
|
+
try {
|
|
246
|
+
return require('./nokhwa-node.freebsd-arm64.node')
|
|
247
|
+
} catch (e) {
|
|
248
|
+
loadErrors.push(e)
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const binding = require('nokhwa-node-freebsd-arm64')
|
|
252
|
+
const bindingPackageVersion = require('nokhwa-node-freebsd-arm64/package.json').version
|
|
253
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
254
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
255
|
+
}
|
|
256
|
+
return binding
|
|
257
|
+
} catch (e) {
|
|
258
|
+
loadErrors.push(e)
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`))
|
|
262
|
+
}
|
|
263
|
+
} else if (process.platform === 'linux') {
|
|
264
|
+
if (process.arch === 'x64') {
|
|
265
|
+
if (isMusl()) {
|
|
266
|
+
try {
|
|
267
|
+
return require('./nokhwa-node.linux-x64-musl.node')
|
|
268
|
+
} catch (e) {
|
|
269
|
+
loadErrors.push(e)
|
|
270
|
+
}
|
|
271
|
+
try {
|
|
272
|
+
const binding = require('nokhwa-node-linux-x64-musl')
|
|
273
|
+
const bindingPackageVersion = require('nokhwa-node-linux-x64-musl/package.json').version
|
|
274
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
275
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
276
|
+
}
|
|
277
|
+
return binding
|
|
278
|
+
} catch (e) {
|
|
279
|
+
loadErrors.push(e)
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
try {
|
|
283
|
+
return require('./nokhwa-node.linux-x64-gnu.node')
|
|
284
|
+
} catch (e) {
|
|
285
|
+
loadErrors.push(e)
|
|
286
|
+
}
|
|
287
|
+
try {
|
|
288
|
+
const binding = require('nokhwa-node-linux-x64-gnu')
|
|
289
|
+
const bindingPackageVersion = require('nokhwa-node-linux-x64-gnu/package.json').version
|
|
290
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
291
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
292
|
+
}
|
|
293
|
+
return binding
|
|
294
|
+
} catch (e) {
|
|
295
|
+
loadErrors.push(e)
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
} else if (process.arch === 'arm64') {
|
|
299
|
+
if (isMusl()) {
|
|
300
|
+
try {
|
|
301
|
+
return require('./nokhwa-node.linux-arm64-musl.node')
|
|
302
|
+
} catch (e) {
|
|
303
|
+
loadErrors.push(e)
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
const binding = require('nokhwa-node-linux-arm64-musl')
|
|
307
|
+
const bindingPackageVersion = require('nokhwa-node-linux-arm64-musl/package.json').version
|
|
308
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
309
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
310
|
+
}
|
|
311
|
+
return binding
|
|
312
|
+
} catch (e) {
|
|
313
|
+
loadErrors.push(e)
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
try {
|
|
317
|
+
return require('./nokhwa-node.linux-arm64-gnu.node')
|
|
318
|
+
} catch (e) {
|
|
319
|
+
loadErrors.push(e)
|
|
320
|
+
}
|
|
321
|
+
try {
|
|
322
|
+
const binding = require('nokhwa-node-linux-arm64-gnu')
|
|
323
|
+
const bindingPackageVersion = require('nokhwa-node-linux-arm64-gnu/package.json').version
|
|
324
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
325
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
326
|
+
}
|
|
327
|
+
return binding
|
|
328
|
+
} catch (e) {
|
|
329
|
+
loadErrors.push(e)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
} else if (process.arch === 'arm') {
|
|
333
|
+
if (isMusl()) {
|
|
334
|
+
try {
|
|
335
|
+
return require('./nokhwa-node.linux-arm-musleabihf.node')
|
|
336
|
+
} catch (e) {
|
|
337
|
+
loadErrors.push(e)
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
const binding = require('nokhwa-node-linux-arm-musleabihf')
|
|
341
|
+
const bindingPackageVersion = require('nokhwa-node-linux-arm-musleabihf/package.json').version
|
|
342
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
343
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
344
|
+
}
|
|
345
|
+
return binding
|
|
346
|
+
} catch (e) {
|
|
347
|
+
loadErrors.push(e)
|
|
348
|
+
}
|
|
349
|
+
} else {
|
|
350
|
+
try {
|
|
351
|
+
return require('./nokhwa-node.linux-arm-gnueabihf.node')
|
|
352
|
+
} catch (e) {
|
|
353
|
+
loadErrors.push(e)
|
|
354
|
+
}
|
|
355
|
+
try {
|
|
356
|
+
const binding = require('nokhwa-node-linux-arm-gnueabihf')
|
|
357
|
+
const bindingPackageVersion = require('nokhwa-node-linux-arm-gnueabihf/package.json').version
|
|
358
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
359
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
360
|
+
}
|
|
361
|
+
return binding
|
|
362
|
+
} catch (e) {
|
|
363
|
+
loadErrors.push(e)
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
} else if (process.arch === 'loong64') {
|
|
367
|
+
if (isMusl()) {
|
|
368
|
+
try {
|
|
369
|
+
return require('./nokhwa-node.linux-loong64-musl.node')
|
|
370
|
+
} catch (e) {
|
|
371
|
+
loadErrors.push(e)
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
const binding = require('nokhwa-node-linux-loong64-musl')
|
|
375
|
+
const bindingPackageVersion = require('nokhwa-node-linux-loong64-musl/package.json').version
|
|
376
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
377
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
378
|
+
}
|
|
379
|
+
return binding
|
|
380
|
+
} catch (e) {
|
|
381
|
+
loadErrors.push(e)
|
|
382
|
+
}
|
|
383
|
+
} else {
|
|
384
|
+
try {
|
|
385
|
+
return require('./nokhwa-node.linux-loong64-gnu.node')
|
|
386
|
+
} catch (e) {
|
|
387
|
+
loadErrors.push(e)
|
|
388
|
+
}
|
|
389
|
+
try {
|
|
390
|
+
const binding = require('nokhwa-node-linux-loong64-gnu')
|
|
391
|
+
const bindingPackageVersion = require('nokhwa-node-linux-loong64-gnu/package.json').version
|
|
392
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
393
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
394
|
+
}
|
|
395
|
+
return binding
|
|
396
|
+
} catch (e) {
|
|
397
|
+
loadErrors.push(e)
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
} else if (process.arch === 'riscv64') {
|
|
401
|
+
if (isMusl()) {
|
|
402
|
+
try {
|
|
403
|
+
return require('./nokhwa-node.linux-riscv64-musl.node')
|
|
404
|
+
} catch (e) {
|
|
405
|
+
loadErrors.push(e)
|
|
406
|
+
}
|
|
407
|
+
try {
|
|
408
|
+
const binding = require('nokhwa-node-linux-riscv64-musl')
|
|
409
|
+
const bindingPackageVersion = require('nokhwa-node-linux-riscv64-musl/package.json').version
|
|
410
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
411
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
412
|
+
}
|
|
413
|
+
return binding
|
|
414
|
+
} catch (e) {
|
|
415
|
+
loadErrors.push(e)
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
try {
|
|
419
|
+
return require('./nokhwa-node.linux-riscv64-gnu.node')
|
|
420
|
+
} catch (e) {
|
|
421
|
+
loadErrors.push(e)
|
|
422
|
+
}
|
|
423
|
+
try {
|
|
424
|
+
const binding = require('nokhwa-node-linux-riscv64-gnu')
|
|
425
|
+
const bindingPackageVersion = require('nokhwa-node-linux-riscv64-gnu/package.json').version
|
|
426
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
427
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
428
|
+
}
|
|
429
|
+
return binding
|
|
430
|
+
} catch (e) {
|
|
431
|
+
loadErrors.push(e)
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
} else if (process.arch === 'ppc64') {
|
|
435
|
+
try {
|
|
436
|
+
return require('./nokhwa-node.linux-ppc64-gnu.node')
|
|
437
|
+
} catch (e) {
|
|
438
|
+
loadErrors.push(e)
|
|
439
|
+
}
|
|
440
|
+
try {
|
|
441
|
+
const binding = require('nokhwa-node-linux-ppc64-gnu')
|
|
442
|
+
const bindingPackageVersion = require('nokhwa-node-linux-ppc64-gnu/package.json').version
|
|
443
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
444
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
445
|
+
}
|
|
446
|
+
return binding
|
|
447
|
+
} catch (e) {
|
|
448
|
+
loadErrors.push(e)
|
|
449
|
+
}
|
|
450
|
+
} else if (process.arch === 's390x') {
|
|
451
|
+
try {
|
|
452
|
+
return require('./nokhwa-node.linux-s390x-gnu.node')
|
|
453
|
+
} catch (e) {
|
|
454
|
+
loadErrors.push(e)
|
|
455
|
+
}
|
|
456
|
+
try {
|
|
457
|
+
const binding = require('nokhwa-node-linux-s390x-gnu')
|
|
458
|
+
const bindingPackageVersion = require('nokhwa-node-linux-s390x-gnu/package.json').version
|
|
459
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
460
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
461
|
+
}
|
|
462
|
+
return binding
|
|
463
|
+
} catch (e) {
|
|
464
|
+
loadErrors.push(e)
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`))
|
|
468
|
+
}
|
|
469
|
+
} else if (process.platform === 'openharmony') {
|
|
470
|
+
if (process.arch === 'arm64') {
|
|
471
|
+
try {
|
|
472
|
+
return require('./nokhwa-node.openharmony-arm64.node')
|
|
473
|
+
} catch (e) {
|
|
474
|
+
loadErrors.push(e)
|
|
475
|
+
}
|
|
476
|
+
try {
|
|
477
|
+
const binding = require('nokhwa-node-openharmony-arm64')
|
|
478
|
+
const bindingPackageVersion = require('nokhwa-node-openharmony-arm64/package.json').version
|
|
479
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
480
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
481
|
+
}
|
|
482
|
+
return binding
|
|
483
|
+
} catch (e) {
|
|
484
|
+
loadErrors.push(e)
|
|
485
|
+
}
|
|
486
|
+
} else if (process.arch === 'x64') {
|
|
487
|
+
try {
|
|
488
|
+
return require('./nokhwa-node.openharmony-x64.node')
|
|
489
|
+
} catch (e) {
|
|
490
|
+
loadErrors.push(e)
|
|
491
|
+
}
|
|
492
|
+
try {
|
|
493
|
+
const binding = require('nokhwa-node-openharmony-x64')
|
|
494
|
+
const bindingPackageVersion = require('nokhwa-node-openharmony-x64/package.json').version
|
|
495
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
496
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
497
|
+
}
|
|
498
|
+
return binding
|
|
499
|
+
} catch (e) {
|
|
500
|
+
loadErrors.push(e)
|
|
501
|
+
}
|
|
502
|
+
} else if (process.arch === 'arm') {
|
|
503
|
+
try {
|
|
504
|
+
return require('./nokhwa-node.openharmony-arm.node')
|
|
505
|
+
} catch (e) {
|
|
506
|
+
loadErrors.push(e)
|
|
507
|
+
}
|
|
508
|
+
try {
|
|
509
|
+
const binding = require('nokhwa-node-openharmony-arm')
|
|
510
|
+
const bindingPackageVersion = require('nokhwa-node-openharmony-arm/package.json').version
|
|
511
|
+
if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
512
|
+
throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
513
|
+
}
|
|
514
|
+
return binding
|
|
515
|
+
} catch (e) {
|
|
516
|
+
loadErrors.push(e)
|
|
517
|
+
}
|
|
518
|
+
} else {
|
|
519
|
+
loadErrors.push(new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`))
|
|
520
|
+
}
|
|
521
|
+
} else {
|
|
522
|
+
loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`))
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
nativeBinding = requireNative()
|
|
527
|
+
|
|
528
|
+
if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
|
|
529
|
+
let wasiBinding = null
|
|
530
|
+
let wasiBindingError = null
|
|
531
|
+
try {
|
|
532
|
+
wasiBinding = require('./nokhwa-node.wasi.cjs')
|
|
533
|
+
nativeBinding = wasiBinding
|
|
534
|
+
} catch (err) {
|
|
535
|
+
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
536
|
+
wasiBindingError = err
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
if (!nativeBinding) {
|
|
540
|
+
try {
|
|
541
|
+
wasiBinding = require('nokhwa-node-wasm32-wasi')
|
|
542
|
+
nativeBinding = wasiBinding
|
|
543
|
+
} catch (err) {
|
|
544
|
+
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
545
|
+
wasiBindingError.cause = err
|
|
546
|
+
loadErrors.push(err)
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if (process.env.NAPI_RS_FORCE_WASI === 'error' && !wasiBinding) {
|
|
551
|
+
const error = new Error('WASI binding not found and NAPI_RS_FORCE_WASI is set to error')
|
|
552
|
+
error.cause = wasiBindingError
|
|
553
|
+
throw error
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
if (!nativeBinding) {
|
|
558
|
+
if (loadErrors.length > 0) {
|
|
559
|
+
throw new Error(
|
|
560
|
+
`Cannot find native binding. ` +
|
|
561
|
+
`npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ` +
|
|
562
|
+
'Please try `npm i` again after removing both package-lock.json and node_modules directory.',
|
|
563
|
+
{
|
|
564
|
+
cause: loadErrors.reduce((err, cur) => {
|
|
565
|
+
cur.cause = err
|
|
566
|
+
return cur
|
|
567
|
+
}),
|
|
568
|
+
},
|
|
569
|
+
)
|
|
570
|
+
}
|
|
571
|
+
throw new Error(`Failed to load native binding`)
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
module.exports = nativeBinding
|
|
575
|
+
module.exports.Camera = nativeBinding.Camera
|
|
576
|
+
module.exports.CameraBuffer = nativeBinding.CameraBuffer
|
|
577
|
+
module.exports.allKnownCameraControls = nativeBinding.allKnownCameraControls
|
|
578
|
+
module.exports.ApiBackend = nativeBinding.ApiBackend
|
|
579
|
+
module.exports.bufBgrToRgb = nativeBinding.bufBgrToRgb
|
|
580
|
+
module.exports.bufMjpegToRgb = nativeBinding.bufMjpegToRgb
|
|
581
|
+
module.exports.bufNv12ToRgb = nativeBinding.bufNv12ToRgb
|
|
582
|
+
module.exports.bufYuyv422ToRgb = nativeBinding.bufYuyv422ToRgb
|
|
583
|
+
module.exports.colorFrameFormats = nativeBinding.colorFrameFormats
|
|
584
|
+
module.exports.FrameFormat = nativeBinding.FrameFormat
|
|
585
|
+
module.exports.frameFormats = nativeBinding.frameFormats
|
|
586
|
+
module.exports.KnownCameraControl = nativeBinding.KnownCameraControl
|
|
587
|
+
module.exports.listCameras = nativeBinding.listCameras
|
|
588
|
+
module.exports.mjpegToRgb = nativeBinding.mjpegToRgb
|
|
589
|
+
module.exports.nativeApiBackend = nativeBinding.nativeApiBackend
|
|
590
|
+
module.exports.nokhwaCheck = nativeBinding.nokhwaCheck
|
|
591
|
+
module.exports.nv12ToRgb = nativeBinding.nv12ToRgb
|
|
592
|
+
module.exports.query = nativeBinding.query
|
|
593
|
+
module.exports.RequestedFormatType = nativeBinding.RequestedFormatType
|
|
594
|
+
module.exports.yuyv422PredictedSize = nativeBinding.yuyv422PredictedSize
|
|
595
|
+
module.exports.yuyv422ToRgb = nativeBinding.yuyv422ToRgb
|
package/package.json
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nokhwa-node",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Node.js bindings for nokhwa camera library using napi-rs",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+ssh://git@github.com/nglmercer/nokhwa-node.git"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"browser": "browser.js",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"camera",
|
|
14
|
+
"webcam",
|
|
15
|
+
"video",
|
|
16
|
+
"napi-rs",
|
|
17
|
+
"NAPI",
|
|
18
|
+
"N-API",
|
|
19
|
+
"Rust",
|
|
20
|
+
"node-addon",
|
|
21
|
+
"node-addon-api",
|
|
22
|
+
"nokhwa"
|
|
23
|
+
],
|
|
24
|
+
"files": [
|
|
25
|
+
"index.d.ts",
|
|
26
|
+
"index.js",
|
|
27
|
+
"browser.js"
|
|
28
|
+
],
|
|
29
|
+
"napi": {
|
|
30
|
+
"binaryName": "nokhwa-node",
|
|
31
|
+
"targets": [
|
|
32
|
+
"x86_64-pc-windows-msvc",
|
|
33
|
+
"x86_64-apple-darwin",
|
|
34
|
+
"x86_64-unknown-linux-gnu",
|
|
35
|
+
"x86_64-unknown-linux-musl",
|
|
36
|
+
"aarch64-unknown-linux-gnu",
|
|
37
|
+
"i686-pc-windows-msvc",
|
|
38
|
+
"aarch64-apple-darwin",
|
|
39
|
+
"x86_64-unknown-freebsd",
|
|
40
|
+
"aarch64-unknown-linux-musl",
|
|
41
|
+
"aarch64-pc-windows-msvc",
|
|
42
|
+
"wasm32-wasip1-threads"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">= 10"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"registry": "https://registry.npmjs.org/",
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"artifacts": "napi artifacts",
|
|
54
|
+
"bench": "tsx benchmark/bench.ts",
|
|
55
|
+
"build": "napi build --platform --release",
|
|
56
|
+
"build:debug": "napi build --platform",
|
|
57
|
+
"format": "run-p format:prettier format:rs format:toml",
|
|
58
|
+
"format:prettier": "prettier . -w",
|
|
59
|
+
"format:toml": "taplo format",
|
|
60
|
+
"format:rs": "cargo fmt",
|
|
61
|
+
"lint": "oxlint .",
|
|
62
|
+
"prepublishOnly": "napi prepublish -t npm",
|
|
63
|
+
"test": "node test-runner.mjs",
|
|
64
|
+
"test:ava": "ava",
|
|
65
|
+
"preversion": "napi build --platform && git add .",
|
|
66
|
+
"version": "napi version",
|
|
67
|
+
"prepare": "husky",
|
|
68
|
+
"bench:debug": "napi build --platform && tsx benchmark/bench.ts"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@emnapi/core": "^1.5.0",
|
|
72
|
+
"@emnapi/runtime": "^1.5.0",
|
|
73
|
+
"@napi-rs/cli": "^3.2.0",
|
|
74
|
+
"@oxc-node/core": "^0.0.35",
|
|
75
|
+
"@taplo/cli": "^0.7.0",
|
|
76
|
+
"@tybys/wasm-util": "^0.10.0",
|
|
77
|
+
"@types/node": "^22.10.5",
|
|
78
|
+
"ava": "^6.4.1",
|
|
79
|
+
"chalk": "^5.6.2",
|
|
80
|
+
"husky": "^9.1.7",
|
|
81
|
+
"lint-staged": "^16.1.6",
|
|
82
|
+
"npm-run-all2": "^8.0.4",
|
|
83
|
+
"oxlint": "^1.14.0",
|
|
84
|
+
"prettier": "^3.6.2",
|
|
85
|
+
"tinybench": "^6.0.0",
|
|
86
|
+
"tsx": "^4.21.0",
|
|
87
|
+
"typescript": "^5.9.2"
|
|
88
|
+
},
|
|
89
|
+
"lint-staged": {
|
|
90
|
+
"*.@(js|ts|tsx)": [
|
|
91
|
+
"oxlint --fix"
|
|
92
|
+
],
|
|
93
|
+
"*.@(js|ts|tsx|yml|yaml|md|json)": [
|
|
94
|
+
"prettier --write"
|
|
95
|
+
],
|
|
96
|
+
"*.toml": [
|
|
97
|
+
"taplo format"
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"ava": {
|
|
101
|
+
"extensions": {
|
|
102
|
+
"ts": "module",
|
|
103
|
+
"js": true
|
|
104
|
+
},
|
|
105
|
+
"timeout": "2m",
|
|
106
|
+
"workerThreads": false
|
|
107
|
+
},
|
|
108
|
+
"prettier": {
|
|
109
|
+
"printWidth": 120,
|
|
110
|
+
"semi": false,
|
|
111
|
+
"trailingComma": "all",
|
|
112
|
+
"singleQuote": true,
|
|
113
|
+
"arrowParens": "always"
|
|
114
|
+
},
|
|
115
|
+
"packageManager": "yarn@4.12.0",
|
|
116
|
+
"optionalDependencies": {
|
|
117
|
+
"nokhwa-node-win32-x64-msvc": "0.1.1",
|
|
118
|
+
"nokhwa-node-darwin-x64": "0.1.1",
|
|
119
|
+
"nokhwa-node-linux-x64-gnu": "0.1.1",
|
|
120
|
+
"nokhwa-node-linux-x64-musl": "0.1.1",
|
|
121
|
+
"nokhwa-node-linux-arm64-gnu": "0.1.1",
|
|
122
|
+
"nokhwa-node-win32-ia32-msvc": "0.1.1",
|
|
123
|
+
"nokhwa-node-darwin-arm64": "0.1.1",
|
|
124
|
+
"nokhwa-node-freebsd-x64": "0.1.1",
|
|
125
|
+
"nokhwa-node-linux-arm64-musl": "0.1.1",
|
|
126
|
+
"nokhwa-node-win32-arm64-msvc": "0.1.1",
|
|
127
|
+
"nokhwa-node-wasm32-wasi": "0.1.1"
|
|
128
|
+
}
|
|
129
|
+
}
|