{"id":14977912,"url":"https://github.com/launchcodedev/pi-camera-connect","last_synced_at":"2025-10-15T00:55:47.225Z","repository":{"id":44152956,"uuid":"126543048","full_name":"launchcodedev/pi-camera-connect","owner":"launchcodedev","description":"Library to capture and stream Raspberry Pi camera data directly to NodeJS","archived":false,"fork":false,"pushed_at":"2023-02-28T20:07:55.000Z","size":376,"stargazers_count":122,"open_issues_count":16,"forks_count":30,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-09T16:19:34.315Z","etag":null,"topics":["camera-stream","jpeg","mjpeg","nodejs","raspberry-pi-camera","video-stream"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/launchcodedev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-23T22:02:45.000Z","updated_at":"2025-03-20T06:57:54.000Z","dependencies_parsed_at":"2024-06-21T17:33:44.999Z","dependency_job_id":"2a2283e8-4b55-4164-ab64-e89e442f163d","html_url":"https://github.com/launchcodedev/pi-camera-connect","commit_stats":{"total_commits":35,"total_committers":7,"mean_commits":5.0,"dds":0.4285714285714286,"last_synced_commit":"60dc66b3c93b4cd8d32a5885c9fe582f3b07c06a"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchcodedev%2Fpi-camera-connect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchcodedev%2Fpi-camera-connect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchcodedev%2Fpi-camera-connect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchcodedev%2Fpi-camera-connect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/launchcodedev","download_url":"https://codeload.github.com/launchcodedev/pi-camera-connect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065281,"owners_count":21041872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["camera-stream","jpeg","mjpeg","nodejs","raspberry-pi-camera","video-stream"],"created_at":"2024-09-24T13:56:32.369Z","updated_at":"2025-10-15T00:55:42.174Z","avatar_url":"https://github.com/launchcodedev.png","language":"TypeScript","readme":"[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/launchcodedev/pi-camera-connect/master/LICENSE)\n[![npm](https://img.shields.io/npm/v/pi-camera-connect.svg)](https://www.npmjs.com/package/pi-camera-connect)\n\n# Pi Camera Connect - for NodeJS\n\n`pi-camera-connect` is a library to capture and stream Raspberry Pi camera data directly to NodeJS.\n\n## Why use this?\n\nThere are many NPM modules for connecting to the Raspberry Pi camera, why use this?\n\n- **Speed:** JPEG images can be captured in ~33ms using a built in MJPEG parser\n- **Efficient:** Pictures and video streams are piped directly into Node as a `Buffer`, keeping all data in memory and eliminating disk I/O\n- **Usable:** Video streams are available as [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable) objects that can be piped or listened to\n- **Tested:** Contains automated tests using Jest\n- **Modern:** Uses the latest ESNext features and up to date development practices\n- **Structure**: Ships with TypeScript definition files\n\n## Install\n\nNPM\n\n```\n$ npm install --save pi-camera-connect\n```\n\nYarn\n\n```\n$ yarn add pi-camera-connect\n```\n\n## Basic Usage\n\n### ESNext Syntax\n\nImage capture:\n\n```javascript\nimport { StillCamera } from 'pi-camera-connect';\nimport * as fs from 'fs';\n\n// Take still image and save to disk\nconst runApp = async () =\u003e {\n  const stillCamera = new StillCamera();\n\n  const image = await stillCamera.takeImage();\n\n  fs.writeFileSync('still-image.jpg', image);\n};\n\nrunApp();\n```\n\nVideo capture:\n\n```javascript\nimport { StreamCamera, Codec } from 'pi-camera-connect';\nimport * as fs from 'fs';\n\n// Capture 5 seconds of H264 video and save to disk\nconst runApp = async () =\u003e {\n  const streamCamera = new StreamCamera({\n    codec: Codec.H264,\n  });\n\n  const videoStream = streamCamera.createStream();\n\n  const writeStream = fs.createWriteStream('video-stream.h264');\n\n  videoStream.pipe(writeStream);\n\n  await streamCamera.startCapture();\n\n  await new Promise(resolve =\u003e setTimeout(() =\u003e resolve(), 5000));\n\n  await streamCamera.stopCapture();\n};\n\nrunApp();\n```\n\n### Compatible Syntax\n\nImage capture:\n\n```javascript\nconst { StillCamera } = require('pi-camera-connect');\n\nconst stillCamera = new StillCamera();\n\nstillCamera.takeImage().then(image =\u003e {\n  fs.writeFileSync('still-image.jpg', image);\n});\n```\n\nVideo capture:\n\n```javascript\nconst { StreamCamera, Codec } = require('pi-camera-connect');\n\nconst streamCamera = new StreamCamera({\n  codec: Codec.H264,\n});\n\nconst writeStream = fs.createWriteStream('video-stream.h264');\n\nconst videoStream = streamCamera.createStream();\n\nvideoStream.pipe(writeStream);\n\nstreamCamera.startCapture().then(() =\u003e {\n  setTimeout(() =\u003e streamCamera.stopCapture(), 5000);\n});\n```\n\n## Capturing an image\n\nThere are 2 ways to capture an image with `pi-camera-connect`:\n\n1. `StillCamera.takeImage()` - _Slow, but higher quality_\n\n   This is equivalent to running the `raspistill` command. Under the hood, the GPU will run a strong noise reduction algorithm to make the image appear higher quality.\n\n   ```javascript\n   import { StillCamera } from 'pi-camera-connect';\n\n   const runApp = async () =\u003e {\n     const stillCamera = new StillCamera();\n\n     const image = await stillCamera.takeImage();\n\n     // Process image...\n   };\n\n   runApp();\n   ```\n\n2. `StreamCamera.takeImage()` - _Fast, but lower quality_\n\n   This works by grabbing a single JPEG frame from a Motion JPEG (MJPEG) video stream . Images captured from the video port tend to have a grainier appearance due to the lack of a strong noise reduction algorithm.\n\n   Using this method, you can capture a JPEG image at more or less the frame rate of the stream, eg. 30 fps = ~33ms capture times.\n\n   ```javascript\n   import { StreamCamera, Codec } from 'pi-camera-connect';\n\n   const runApp = async () =\u003e {\n     const streamCamera = new StreamCamera({\n       codec: Codec.MJPEG,\n     });\n\n     await streamCamera.startCapture();\n\n     const image = await streamCamera.takeImage();\n\n     // Process image...\n\n     await streamCamera.stopCapture();\n   };\n\n   runApp();\n   ```\n\n## Capturing a video stream\n\nCapturing a video stream is easy. There are currently 2 codecs supported: `H264` and `MJPEG`.\n\n### Why **H264** and **MJPEG**?\n\nThe GPU on the Raspberry Pi comes with a hardware-accelerated H264 encoder and JPEG encoder. To capture videos in real time, using these hardware encoders are required.\n\n### Stream\n\nA standard NodeJS [readable stream](https://nodejs.org/api/stream.html#stream_class_stream_readable) is available after calling `createStream()`. As with any readable stream, it can be piped or listened to.\n\n```javascript\nimport { StreamCamera, Codec } from 'pi-camera-connect';\nimport * as fs from 'fs';\n\nconst runApp = async () =\u003e {\n  const streamCamera = new StreamCamera({\n    codec: Codec.H264,\n  });\n\n  const videoStream = streamCamera.createStream();\n\n  const writeStream = fs.createWriteStream('video-stream.h264');\n\n  // Pipe the video stream to our video file\n  videoStream.pipe(writeStream);\n\n  await streamCamera.startCapture();\n\n  // We can also listen to data events as they arrive\n  videoStream.on('data', data =\u003e console.log('New data', data));\n  videoStream.on('end', data =\u003e console.log('Video stream has ended'));\n\n  // Wait for 5 seconds\n  await new Promise(resolve =\u003e setTimeout(() =\u003e resolve(), 5000));\n\n  await streamCamera.stopCapture();\n};\n\nrunApp();\n```\n\nYou can test the video by viewing it in `omxplayer` (ships with Raspbian):\n\n```\n$ omxplayer video-stream.h264\n```\n\nNote that this example produces a raw H264 video. Wrapping it in a video container (eg. MP4, MKV, etc) is out of the scope of this module.\n\n## API\n\n- [`StillCamera`](#stillcamera)\n  - `constructor(options?: StillOptions): StillCamera`\n  - `takeImage(): Promise\u003cBuffer\u003e`\n- [`StreamCamera`](#streamcamera)\n  - `constructor(options?: StreamOptions): StreamCamera`\n  - `startCapture(): Promise\u003cvoid\u003e`\n  - `stopCapture(): Promise\u003cvoid\u003e`\n  - `createStream(): stream.Readable`\n  - `takeImage(): Promise\u003cBuffer\u003e`\n- [`Rotation`](#rotation)\n- [`Flip`](#flip)\n- [`Codec`](#codec)\n- [`SensorMode`](#sensormode)\n- [`ExposureMode`](#exposuremode)\n- [`AwbMode`](#awbmode)\n\n## `StillCamera`\n\nA class for taking still images. Equivalent to running the `raspistill` command.\n\n### `constructor (options?: StillOptions): StillCamera`\n\nInstantiates a new `StillCamera` class.\n\n```javascript\nconst stillCamera = new StillCamera({\n    ...\n});\n```\n\n`StillOptions` are:\n\n- `width: number` - _Default: Max sensor width_\n- `height: number` - _Default: Max sensor height_\n- [`rotation: Rotation`](#rotation) - _Default: `Rotation.Rotate0`_\n- [`flip: Flip`](#flip) - _Default: `Flip.None`_\n- `delay: number` - _Default: `1` ms_\n- `shutter: number` - _Default: Auto calculated based on framerate (1000000µs/fps). Number is in microseconds_\n- `sharpness: number` - _Range: `-100`-`100`; Default: `0`_\n- `contrast: number` - _Range: `-100`-`100`; Default: `0`_\n- `brightness: number` - _Range: `0`-`100`; Default: `50`_\n- `saturation: number` - _Range: `-100`-`100`; Default: `0`_\n- `iso: number` - _Range: `100`-`800`; Default: Auto_\n- `exposureCompensation: number` - _Range: `-10`-`10`; Default: `0`_\n- [`exposureMode: ExposureMode`](#exposuremode) - _Default: `ExposureMode.Auto`_\n- [`awbMode: AwbMode`](#awbmode) - _Default: `AwbMode.Auto`_\n- `analogGain: number` - _Default: `0`_\n- `digitalGain: number` - _Default: `0`_\n\n### `StillCamera.takeImage(): Promise\u003cBuffer\u003e`\n\nTakes a JPEG image from the camera. Returns a `Promise` with a `Buffer` containing the image bytes.\n\n```javascript\nconst stillCamera = new StillCamera();\n\nconst image = await stillCamera.takeImage();\n```\n\n## `StreamCamera`\n\nA class for capturing a stream of camera data, either as `H264` or `MJPEG`.\n\n### `constructor(options?: StreamOptions): StreamCamera`\n\nInstantiates a new `StreamCamera` class.\n\n```javascript\nconst streamCamera = new StreamCamera({\n    ...\n});\n```\n\n`StreamOptions` are:\n\n- `width: number` - _Default: Max sensor width_\n- `height: number` - _Default: Max sensor height_\n- [`rotation: Rotation`](#rotation) - _Default: `Rotation.Rotate0`_\n- [`flip: Flip`](#flip) - _Default: `Flip.None`_\n- `bitRate: number` - _Default: `17000000` (17 Mbps)_\n- `fps: number` - _Default: `30` fps_\n- [`codec: Codec`](#codec) - _Default: `Codec.H264`_\n- [`sensorMode: SensorMode`](#sensormode) - _Default: `SensorMode.AutoSelect`_\n- `shutter: number` - _Default: Auto calculated based on framerate (1000000µs/fps). Number is in microseconds_\n- `sharpness: number` - _Range: `-100`-`100`; Default: `0`_\n- `contrast: number` - _Range: `-100`-`100`; Default: `0`_\n- `brightness: number` - _Range: `0`-`100`; Default: `50`_\n- `saturation: number` - _Range: `-100`-`100`; Default: `0`_\n- `iso: number` - _Range: `100`-`800`; Default: Auto_\n- `exposureCompensation: number` - _Range: `-10`-`10`; Default: `0`_\n- [`exposureMode: ExposureMode`](#exposuremode) - _Default: `ExposureMode.Auto`_\n- [`awbMode: AwbMode`](#awbmode) - _Default: `AwbMode.Auto`_\n- `analogGain: number` - _Default: `0`_\n- `digitalGain: number` - _Default: `0`_\n\n### `startCapture(): Promise\u003cvoid\u003e`\n\nBegins the camera stream. Returns a `Promise` that is resolved when the capture has started.\n\n### `stopCapture(): Promise\u003cvoid\u003e`\n\nEnds the camera stream. Returns a `Promise` that is resolved when the capture has stopped.\n\n### `createStream(): stream.Readable`\n\nCreates a [`readable stream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) of video data. There is no limit to the number of streams you can create.\n\nBe aware that, as with any readable stream, data will buffer in memory until it is read. If you create a video stream but do not read its data, your program will quickly run out of memory.\n\nWays to read data so that it does not remain buffered in memory include:\n\n- Switching the stream to 'flowing' mode by calling either `resume()`, `pipe()`, or attaching a listener to the `'data'` event\n- Calling `read()` when the stream is in 'paused' mode\n\nSee the [readable stream documentation](https://nodejs.org/api/stream.html#stream_two_modes) for more information on flowing/paused modes.\n\n```javascript\nconst streamCamera = new StreamCamera({\n  codec: Codec.H264,\n});\n\nconst videoStream = streamCamera.createStream();\n\nawait streamCamera.startCapture();\n\nvideoStream.on('data', data =\u003e console.log('New video data', data));\n\n// Wait 5 seconds\nawait new Promise(resolve =\u003e setTimeout(() =\u003e resolve(), 5000));\n\nawait streamCamera.stopCapture();\n```\n\n### `takeImage(): Promise\u003cBuffer\u003e`\n\nTakes a JPEG image frame from an MJPEG camera stream, resulting in very fast image captures. Returns a `Promise` with a `Buffer` containing the image bytes.\n\n_Note: `StreamOptions.codec` must be set to `Codec.MJPEG`, otherwise `takeImage()` with throw an error._\n\n```javascript\nconst streamCamera = new StreamCamera({\n  codec: Codec.MJPEG,\n});\n\nawait streamCamera.startCapture();\n\nconst image = await streamCamera.takeImage();\n\nawait streamCamera.stopCapture();\n```\n\n## `Rotation`\n\nImage rotation options.\n\n- `Rotation.Rotate0`\n- `Rotation.Rotate90`\n- `Rotation.Rotate180`\n- `Rotation.Rotate270`\n\n```javascript\nimport { Rotation } from 'pi-camera-connect';\n```\n\n## `Flip`\n\nImage flip options.\n\n- `Flip.None`\n- `Flip.Horizontal`\n- `Flip.Vertical`\n- `Flip.Both`\n\n```javascript\nimport { Flip } from 'pi-camera-connect';\n```\n\n## `Codec`\n\nStream codec options.\n\n- `Codec.H264`\n- `Codec.MJPEG`\n\n```javascript\nimport { Codec } from 'pi-camera-connect';\n```\n\n## `SensorMode`\n\nStream sensor mode options.\n\n- `SensorMode.AutoSelect`\n- `SensorMode.Mode1`\n- `SensorMode.Mode2`\n- `SensorMode.Mode3`\n- `SensorMode.Mode4`\n- `SensorMode.Mode5`\n- `SensorMode.Mode6`\n- `SensorMode.Mode7`\n\n```javascript\nimport { SensorMode } from 'pi-camera-connect';\n```\n\nThese are slightly different depending on the version of Raspberry Pi camera you are using.\n\n#### Camera version 1.x (OV5647):\n\n| Mode | Size                | Aspect Ratio | Frame rates | FOV     | Binning       |\n| ---- | ------------------- | ------------ | ----------- | ------- | ------------- |\n| 0    | automatic selection |              |             |         |               |\n| 1    | 1920x1080           | 16:9         | 1-30fps     | Partial | None          |\n| 2    | 2592x1944           | 4:3          | 1-15fps     | Full    | None          |\n| 3    | 2592x1944           | 4:3          | 0.1666-1fps | Full    | None          |\n| 4    | 1296x972            | 4:3          | 1-42fps     | Full    | 2x2           |\n| 5    | 1296x730            | 16:9         | 1-49fps     | Full    | 2x2           |\n| 6    | 640x480             | 4:3          | 42.1-60fps  | Full    | 2x2 plus skip |\n| 7    | 640x480             | 4:3          | 60.1-90fps  | Full    | 2x2 plus skip |\n\n#### Camera version 2.x (IMX219):\n\n| Mode | Size                | Aspect Ratio | Frame rates | FOV     | Binning |\n| ---- | ------------------- | ------------ | ----------- | ------- | ------- |\n| 0    | automatic selection |              |             |         |         |\n| 1    | 1920x1080           | 16:9         | 0.1-30fps   | Partial | None    |\n| 2    | 3280x2464           | 4:3          | 0.1-15fps   | Full    | None    |\n| 3    | 3280x2464           | 4:3          | 0.1-15fps   | Full    | None    |\n| 4    | 1640x1232           | 4:3          | 0.1-40fps   | Full    | 2x2     |\n| 5    | 1640x922            | 16:9         | 0.1-40fps   | Full    | 2x2     |\n| 6    | 1280x720            | 16:9         | 40-90fps    | Partial | 2x2     |\n| 7    | 640x480             | 4:3          | 40-90fps    | Partial | 2x2     |\n\n## `ExposureMode`\n\nExposure mode options.\n\n- `ExposureMode.Off`\n- `ExposureMode.Auto`\n- `ExposureMode.Night`\n- `ExposureMode.NightPreview`\n- `ExposureMode.Backlight`\n- `ExposureMode.Spotlight`\n- `ExposureMode.Sports`\n- `ExposureMode.Snow`\n- `ExposureMode.Beach`\n- `ExposureMode.VeryLong`\n- `ExposureMode.FixedFps`\n- `ExposureMode.AntiShake`\n- `ExposureMode.Fireworks`\n\n```javascript\nimport { ExposureMode } from 'pi-camera-connect';\n```\n\n## `AwbMode`\n\nWhite balance mode options.\n\n- `AwbMode.Off`\n- `AwbMode.Auto`\n- `AwbMode.Sun`\n- `AwbMode.Cloud`\n- `AwbMode.Shade`\n- `AwbMode.Tungsten`\n- `AwbMode.Fluorescent`\n- `AwbMode.Incandescent`\n- `AwbMode.Flash`\n- `AwbMode.Horizon`\n- `AwbMode.GreyWorld`\n\n```javascript\nimport { AwbMode } from 'pi-camera-connect';\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaunchcodedev%2Fpi-camera-connect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaunchcodedev%2Fpi-camera-connect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaunchcodedev%2Fpi-camera-connect/lists"}