Captures frames from a V4L2 camera and publishes them as std/media/v1/Image: an Arrow struct of width, height, encoding and data, so a receiver needs nothing from the message metadata. For a compressed encoding the recorded dimensions are the image's, not the length of the payload. Based on opencv-video-capture from dora-hub, with three changes. The output is the typed image struct rather than a flat UInt8 buffer plus metadata. Camera selection by id reads /dev/v4l/by-id/ only; the upstream macOS system_profiler and Windows PowerShell enumeration is not carried. CAPTURE_FRAMES bounds a run so a test ends on its own, in place of upstream's ten-second CI cutoff -- a timeout would have made the CI step exit non-zero. CI=true keeps a failed capture from raising, publishing a labelled black frame instead, which is what lets dataflow.yml run on a machine with no camera. Two dataflows, run one at a time, as dora has no cross-dataflow wiring: dataflow.yml is the camera alone and the CI gate; dataflow_view.yml wires it into dora-image-view and is not run by CI, since it fetches that node over the network and needs a tag to exist there.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# Node manifest: the typed contract a consumer wires against.
|
||||
#
|
||||
# No source package is shared between node repositories, so this file and its
|
||||
# type URNs are the only contract a consumer has. `dora validate` checks a
|
||||
# dataflow against it without running the node, so CI needs neither a camera nor
|
||||
# OpenCV.
|
||||
apiVersion: 1
|
||||
name: dora-webcam
|
||||
namespace: liria
|
||||
description: Captures frames from a webcam and publishes them as std/media/v1/Image
|
||||
categories: [sensor]
|
||||
keywords: [opencv, camera, webcam, video, capture, image, v4l2]
|
||||
|
||||
runtime: python
|
||||
entrypoint: dora-webcam
|
||||
# `dora build --uv` / `dora run --uv` rewrites this to `uv pip install .` and
|
||||
# gives the node its own managed venv under `.dora/python-envs/`, so the
|
||||
# dependencies it sees at runtime are the ones installed here.
|
||||
build: pip install .
|
||||
dora: ">=1.0"
|
||||
|
||||
inputs:
|
||||
tick:
|
||||
required: true
|
||||
description: >-
|
||||
Reads and publishes one frame. Wire to dora/timer/millis/N. The node stops
|
||||
when this input closes.
|
||||
|
||||
outputs:
|
||||
image:
|
||||
type: std/media/v1/Image
|
||||
description: >-
|
||||
Captured frame as an Arrow struct {width, height, encoding, data}. For a
|
||||
compressed encoding, width and height are the image's dimensions rather
|
||||
than the length of data, so a receiver can size a buffer without decoding
|
||||
first.
|
||||
|
||||
env:
|
||||
CAMERA_ID:
|
||||
description: >-
|
||||
Substring of an entry in /dev/v4l/by-id/. Stable across reboots and across
|
||||
which USB port the camera is in, unlike an index, so it takes precedence
|
||||
over CAPTURE_PATH. Linux only.
|
||||
CAPTURE_PATH:
|
||||
default: "0"
|
||||
description: Device path such as /dev/video1, or an index. A numeric string is read as an index.
|
||||
IMAGE_WIDTH:
|
||||
type: int
|
||||
description: Requested capture width; frames are also resized to it. Defaults to the camera's native width.
|
||||
IMAGE_HEIGHT:
|
||||
type: int
|
||||
description: Requested capture height; frames are also resized to it. Defaults to the camera's native height.
|
||||
ENCODING:
|
||||
default: bgr8
|
||||
description: One of bgr8, rgb8, yuv420, jpeg/jpg/jpe, png, bmp, webp.
|
||||
JPEG_QUALITY:
|
||||
type: int
|
||||
default: 95
|
||||
description: Quality 0-100, used only by the JPEG encodings.
|
||||
FLIP:
|
||||
description: Flip the frame. One of VERTICAL, HORIZONTAL or BOTH. Unset means no flip.
|
||||
CAPTURE_FRAMES:
|
||||
type: int
|
||||
default: 0
|
||||
description: >-
|
||||
Stop after this many frames. 0, the default, runs until the tick input
|
||||
closes. A positive count is what lets a test run the dataflow to
|
||||
completion rather than killing it on a timeout.
|
||||
CI:
|
||||
type: bool
|
||||
description: >-
|
||||
When true, a failed read publishes a labelled black frame instead of
|
||||
raising, which is what lets the dataflow run on a machine with no camera.
|
||||
|
||||
example: |
|
||||
- id: camera
|
||||
git: ssh://git@gitea.liria.cl:5001/liria/dora-webcam.git
|
||||
tag: v0.1.0
|
||||
build: pip install .
|
||||
path: dora-webcam
|
||||
inputs:
|
||||
tick: dora/timer/millis/33
|
||||
outputs:
|
||||
- image
|
||||
Reference in New Issue
Block a user