npm package: @kybarg/camera
Description: Native Node.js addon for high-performance Windows camera capture using Media Foundation. Select native formats (MJPEG/NV12/YUY2), receive raw sample buffers, and recover from sleep/device loss.
Latest version: 0.0.15

# Camera Device Management Library

[![npm version](https://img.shields.io/npm/v/@kybarg/camera.svg)](https://www.npmjs.com/package/@kybarg/camera)
[![npm downloads](https://img.shields.io/npm/dm/@kybarg/camera.svg)](https://www.npmjs.com/package/@kybarg/camera)
[![license](https://img.shields.io/github/license/kybarg/camera.svg)](LICENSE)
[![github stars](https://img.shields.io/github/stars/kybarg/camera?style=social)](https://github.com/kybarg/camera)

Node.js native addon for Windows camera capture using the Media Foundation API.

## Highlights

- Format selection: choose native subtypes such as `MJPEG`, `NV12`, `YUY2`, `RGB32`, or supply a GUID string.
- Output format conversion: use `setOutputFormat('MJPEG')` to automatically convert frames to JPEG regardless of native camera format.
- Promise-based async API and TypeScript typings included.

## Installation

```powershell
npm install
npm run build
```

Notes: building the native addon requires Visual Studio Build Tools and Python (for `node-gyp`).

## Quick Examples

### JavaScript (minimal)

```javascript
const Camera = require('@kybarg/camera');

async function main() {
  const cam = new Camera();
  const devices = await cam.enumerateDevices();
  if (!devices.length) return console.log('No cameras');

  await cam.claimDevice(devices[0].symbolicLink);

  // Choose a supported format from getSupportedFormats()
  const formats = await cam.getSupportedFormats();
  const fmt = formats[0]; // or pick by resolution/frameRate
  await cam.setFormat(fmt);

  // Convert all frames to JPEG automatically
  await cam.setOutputFormat('MJPEG');

  cam.on('frame', (buf) => {
    // buf is always a JPEG buffer when setOutputFormat('MJPEG') is used
    console.log('JPEG frame bytes:', buf.length);
  });

  await cam.startCapture();

  // stop later
  setTimeout(async () => {
    await cam.stopCapture();
    await cam.releaseDevice();
  }, 5000);
}

main().catch(console.error);
```

When `setOutputFormat('MJPEG')` is set, frames are automatically converted to JPEG regardless of the native camera format (YUY2, NV12, RGB32, etc.). If the native format is already MJPEG, no conversion occurs (pass-through).

## API Overview

All async methods return Promises. See `index.d.ts` for full TypeScript types.

Camera methods:

- `enumerateDevices(): Promise<DeviceInfo[]>` — list attached cameras.
- `claimDevice(symbolicLink): Promise<OperationResult>` — claim exclusive use of a device.
- `releaseDevice(): Promise<OperationResult>` — release claimed device.
- `getSupportedFormats(): Promise<CameraFormat[]>` — returns formats with `{ subtype, width, height, frameRate, guid }`.
- `setFormat(format: CameraFormat): Promise<SetFormatResult>` — set native capture format.
- `setOutputFormat(format?: string): Promise<OperationResult>` — set output format conversion (see below).
- `startCapture(): Promise<OperationResult>` — begin streaming; frames are emitted as `'frame'` events.
- `stopCapture(): Promise<OperationResult>` — stop streaming.
- `getDimensions(): CameraDimensions` — get current width/height.
- `isCapturing(): boolean` — check capture state.

Events:

- `'frame'` — emitted with a single argument: `Buffer` containing the raw sample bytes for that sample.

## Output Format Conversion

Use `setOutputFormat()` to automatically convert frames to a different format:

```javascript
// Convert all frames to JPEG (works with any native format: YUY2, NV12, RGB32, etc.)
await cam.setOutputFormat('MJPEG');

// Disable conversion (return raw native frames)
await cam.setOutputFormat(null);
```

**Supported output formats:**
- `'MJPEG'` — encode frames as JPEG using Windows Imaging Component (WIC)

**Supported input formats for MJPEG output:**
- `RGB32` (BGRA) — direct encoding
- `RGB24` (BGR) — direct encoding
- `YUY2` — converted to RGB, then encoded
- `NV12` — converted to RGB, then encoded

If `setOutputFormat()` is not called or set to `null`, raw native frames are delivered (original behavior).

## Examples and Tests

Run the examples:

```powershell
npm run example
# or
node examples/example.js

# recovery test (non-interactive)
node examples/recovery_test.js
```

## Building

```powershell
npm install
npm run build
```

Requirements: Windows 10/11, Visual Studio Build Tools (or VS), Python 3.x for node-gyp.

## Notes

- Use `setOutputFormat('MJPEG')` to get JPEG frames from any camera format.
- Without `setOutputFormat()`, raw native frames are delivered (MJPEG, YUY2, NV12, etc.).
- The `setFormat()` API accepts format objects from `getSupportedFormats()`.

## License

See [LICENSE](LICENSE).