Rhopoint Instruments Manual
Esta página ainda não foi traduzida e é apresentada em inglês.

Image Streams

Image streams expose a continuous, low-latency video-like feed from a device's camera. They are intended for live preview, alignment and focus assistance — not for archival capture (use measurements for that). A stream is configured once via POST .../start, then consumed either as a Server-Sent-Events feed for real-time delivery or polled frame-by-frame via the snapshot endpoint.

Endpoints Overview

Method Endpoint Description
POST /v1/devices/{deviceId}/image-streams/{sourceKey}/start Start a stream for a specific image source
POST /v1/devices/{deviceId}/image-streams/{sourceKey}/configure Change exposure / scale / encoding while running
GET /v1/devices/{deviceId}/image-streams/{sourceKey}/stream Subscribe to live frames via SSE (text/event-stream)
GET /v1/devices/{deviceId}/image-streams/{sourceKey}/snapshot Pull a single frame (binary image)
GET /v1/devices/{deviceId}/image-streams List all active streams on a connected device
DELETE /v1/devices/{deviceId}/image-streams/{sourceKey} Stop and tear down the stream

Source Keys

A device may expose more than one camera or imaging path. Each is addressed by a sourceKey. For Aesthetix devices the available keys are:

sourceKey Camera
spec Specular path
aspec Aspecular path

Other device classes may expose different keys; consult the device's documentation.

Lifecycle

   ┌──────────────────────────────┐
   │  POST .../{sourceKey}/start  │  ← configure exposure, scale, encoding
   └──────────────┬───────────────┘
                  │
        ┌─────────┴─────────┐
        │                   │
        ▼                   ▼
  GET .../stream      GET .../snapshot
   (SSE feed)         (single frame)
        │                   │
        │   POST .../configure (optional, while running)
        │                   │
        └─────────┬─────────┘
                  ▼
   ┌──────────────────────────────┐
   │  DELETE .../{sourceKey}      │
   └──────────────────────────────┘

A stream remains active until explicitly stopped via DELETE or until the device is disconnected. Reconnecting to the device does not automatically restore previously running streams.

Starting a Stream

POST /v1/devices/{deviceId}/image-streams/{sourceKey}/start
Content-Type: application/json

{
  "exposureTimeMilliseconds": 50,
  "scaleFactor": 0.5,
  "mimeType": "image/jpeg",
  "quality": 0.85
}
curl -X POST http://localhost:42042/v1/devices/12f1d7dd07ac42a088c8f961b39d68ff/image-streams/aspec/start \
  -H "Content-Type: application/json" \
  -d '{ "exposureTimeMilliseconds": 50, "scaleFactor": 0.5, "mimeType": "image/jpeg", "quality": 0.85 }'

Request Body

All fields are optional — omit them to use the server defaults.

Field Type Default Description
exposureTimeMilliseconds double device-dependent Sensor exposure per frame. Typical range 1–1000 ms. Higher values yield brighter frames but lower frame rate.
scaleFactor double 1.0 Downscaling factor applied server-side before encoding. Lower values reduce bandwidth and CPU at the cost of resolution. Typical range 0.1–1.0.
mimeType string "image/png" Per-frame encoding. One of image/png or image/jpeg. PNG is lossless and larger, JPEG smaller and lossy.
quality double 0.85 JPEG quality (0.1–1.0). Ignored when mimeType is image/png.

Response

{
  "deviceId": "12f1d7dd07ac42a088c8f961b39d68ff",
  "sourceKey": "aspec",
  "exposureTimeMilliseconds": 50,
  "scaleFactor": 0.5,
  "mimeType": "image/jpeg",
  "quality": 0.85,
  "startedAt": "2025-11-12T08:20:15.4567890+00:00",
  "status": "active"
}

Consuming the Stream (SSE)

GET /v1/devices/{deviceId}/image-streams/{sourceKey}/stream
Accept: text/event-stream

The response is a Server-Sent-Events stream (RFC 8895). The hub sets Content-Type: text/event-stream, Cache-Control: no-cache, Connection: keep-alive. Each frame arrives as one SSE event:

data: {"mimeType":"image/jpeg","image":"<base64-encoded image bytes>","timestamp":"2025-11-12T08:20:15.5123456+00:00"}

Event Payload

Field Type Description
mimeType string MIME type of the encoded frame (matches the stream's current mimeType).
image string Base64-encoded image bytes. Decode and feed directly to your image viewer.
timestamp string ISO-8601 capture time of the frame (with +00:00 UTC offset). Useful for measuring end-to-end latency.

Error Events

If the device errors out mid-stream, an SSE event with event: error is sent before the connection closes:

event: error
data: {"errorCode":"<code>","message":"<message>"}

Treat this as a terminal event — re-subscribe by issuing GET .../stream again, or stop and recreate the stream if the underlying error was caused by a configuration mismatch.

Following the Stream from the Shell

curl -N http://localhost:42042/v1/devices/12f1d7dd07ac42a088c8f961b39d68ff/image-streams/aspec/stream

-N disables curl's output buffering so each event prints as it arrives. Useful for smoke-testing the stream without writing a client.

Consuming the Stream from a Browser

EventSource is the standard Web API for SSE and the easiest way to consume the feed. The hub's bundled demo app (/app/) uses exactly this pattern:

const url = `http://localhost:42042/v1/devices/${deviceId}/image-streams/${sourceKey}/stream`;
const source = new EventSource(url);

source.onmessage = (event) => {
    const { mimeType, image, timestamp } = JSON.parse(event.data);
    document.getElementById('preview').src = `data:${mimeType};base64,${image}`;
};

source.addEventListener('error', () => {
    source.close();   // terminal — re-subscribe by creating a new EventSource
});

The data: URL form works directly in <img> tags, <canvas>.drawImage() and createImageBitmap() without an explicit Base64 decode step.

Snapshot — Single Frame

GET /v1/devices/{deviceId}/image-streams/{sourceKey}/snapshot
curl -o frame.jpg \
  http://localhost:42042/v1/devices/12f1d7dd07ac42a088c8f961b39d68ff/image-streams/aspec/snapshot

Returns one frame as a raw binary image with the Content-Type set to the stream's current mimeType (image/png, image/jpeg, or image/bmp). Use this when you need a single frame on demand and do not want the overhead of opening an SSE connection.

Snapshots and SSE both read from the same underlying camera. Pulling a snapshot while an SSE feed is active competes for the next frame and is rarely useful. The Elements Hub demo app disables the snapshot button while SSE is running for this reason.

Reconfiguring a Running Stream

POST /v1/devices/{deviceId}/image-streams/{sourceKey}/configure
Content-Type: application/json

{
  "exposureTimeMilliseconds": 100,
  "scaleFactor": 0.75
}

The same field set as start; only the fields you include are changed. Already-subscribed SSE clients keep their connection — subsequent frames simply use the new configuration. Use this for live UI sliders that adjust exposure or scaling without forcing the user to disconnect and reconnect.

Listing Active Streams

GET /v1/devices/{deviceId}/image-streams

Returns an array of ImageStreamResponse records (same shape as the start response), one per sourceKey that currently has an active stream on the device. An empty array means no stream is currently running.

Stopping a Stream

DELETE /v1/devices/{deviceId}/image-streams/{sourceKey}
curl -X DELETE http://localhost:42042/v1/devices/12f1d7dd07ac42a088c8f961b39d68ff/image-streams/aspec

Stops the stream and releases the camera-side resources. Any SSE consumers see the connection close immediately after the next pending frame. DELETE is idempotent at the API level — calling it a second time returns 404 (E37), which most clients can ignore safely on shutdown paths.

Best Practices

  • Start before subscribe: always issue POST .../start before GET .../stream. Subscribing without a started stream returns 404 (E37).
  • Set scaleFactor for the consumer: a 0.5 factor cuts bandwidth and CPU to roughly a quarter without a noticeable difference for live-preview use cases. Full-resolution streaming is rarely the right default.
  • Prefer JPEG for live preview: at quality 0.85 the file size is typically 5–10× smaller than PNG, and the artefacts are invisible at preview resolutions.
  • Close EventSource on tab hide: browsers throttle background tabs, which can starve a hot SSE connection. Listen for visibilitychange and close/reopen the stream as needed.
  • Reconfigure rather than restart: POST .../configure is faster than stop + start because the camera does not reinitialise.
  • Stop on disconnect: explicit DELETE on shutdown frees the camera immediately. POST /v1/lifecycle/shutdown will also stop all streams, but explicit cleanup surfaces errors earlier.

Error Cases

Condition HTTP Error Code
Connected device not found 404 E5
Stream not started (subscribe/snapshot/configure/stop without a prior start) 404 E37
Unsupported sourceKey for the device 404 device-class–specific

See Error Handling for the response format.