lametric-py

Streaming

Overview

LaMetric SKY supports the LaMetric Streaming Protocol (LMSP) over UDP. In this package, the flow is:

  1. Read stream metadata with await device.stream_state
  2. Start a stream with await device.start_stream(config)
  3. Send raw RGB888 frames with await device.send_stream_data(session_id, frame)
  4. Stop the stream with await device.stop_stream()

Start a Stream

from lametric import (
    CanvasFillType,
    CanvasPostProcess,
    CanvasPostProcessType,
    CanvasRenderMode,
    StreamConfig,
)

config = StreamConfig(
    fill_type=CanvasFillType.SCALE,
    render_mode=CanvasRenderMode.PIXEL,
    post_process=CanvasPostProcess(type=CanvasPostProcessType.NONE),
)

session_id = await device.start_stream(config)

To apply a post-processing effect, set type=CanvasPostProcessType.EFFECT and supply params:

from lametric import (
    CanvasFadingPixelsEffectParameters,
    CanvasPostProcessEffectType,
    CanvasPostProcessParameters,
)

config = StreamConfig(
    fill_type=CanvasFillType.SCALE,
    render_mode=CanvasRenderMode.PIXEL,
    post_process=CanvasPostProcess(
        type=CanvasPostProcessType.EFFECT,
        params=CanvasPostProcessParameters(
            effect_type=CanvasPostProcessEffectType.FADING_PIXELS,
            effect_params=CanvasFadingPixelsEffectParameters(
                smooth=True,
                pixel_fill=0.8,
                fade_speed=0.5,
                pixel_base=0.2,
            ),
        ),
    ),
)

Packet Format

send_stream_data builds one LMSP packet with this structure using little-endian byte order:

The implementation currently sends one full-canvas area starting at (0, 0). Protocol name, version, port, and canvas size are taken from the device state, which keeps the packet format aligned with future firmware changes.

Frame Data

The payload for send_stream_data must be full-frame RGB888 data:

stream_state = await device.stream_state
width = stream_state.canvas.pixel.size.width
height = stream_state.canvas.pixel.size.height
frame = bytes([255, 0, 0] * (width * height))  # full red frame
await device.send_stream_data(session_id, frame)

The expected length is width * height * 3 bytes.

Notes