Skip to content

IDS: Stream Live Video

SUMMARY

Stream continuous color frames at a controlled frame rate, JPEG-encode each frame to reduce bandwidth, and visualize the live feed with Rerun.

Example

Code

python
"""
Connect to an IDS camera, get/set parameters, and stream live video.

Run from a terminal to avoid issues with Rerun's spawn mode.
"""
import time
from loguru import logger

import cv2
import rerun as rr

from medulla.cameras import ids


def main():
    camera = ids.IDS(
        name="my_ids_camera",
        serial_number="4108909352",
        load_factory_defaults=False
    )
    try:
        rr.init("IDS_Example", spawn=True)
        camera.connect()

        logger.info(f"AcquisitionFrameRate: {camera.get_parameter('AcquisitionFrameRate')}")
        logger.info(f"ExposureTime: {camera.get_parameter('ExposureTime')}")
        logger.info(f"DeviceLinkThroughputLimit: {camera.get_parameter('DeviceLinkThroughputLimit')}")

        camera.set_parameter('ExposureTime', 35000.0)
        camera.set_parameter('AcquisitionFrameRate', 14.0)

        end_time = time.time() + 10
        while time.time() < end_time:
            image = camera.capture_video_color_frame()
            if image is not None:
                _, encoded = cv2.imencode(
                    '.jpg',
                    image,
                    [cv2.IMWRITE_JPEG_QUALITY, 80]
                )
                rr.log(
                    "Continuous_Image_Capture",
                    rr.EncodedImage(contents=encoded, media_type="image/jpeg")
                )
    except Exception as e:
        logger.error(f"Unable to run video capture. {type(e).__name__}: {e}")
    finally:
        camera.disconnect()


if __name__ == "__main__":
    main()

Explanation

Now, let’s break down the code piece by piece.

The camera object is created the same way as in the single-image example — with a name, serial_number, and load_factory_defaults=False to preserve any settings configured in IDS Peak Cockpit.

python
camera = ids.IDS(
    name="my_ids_camera",
    serial_number="4108909352",
    load_factory_defaults=False
)

After opening the Rerun viewer and connecting, all three parameters supported by the IDS class are read and logged before any changes are made. This gives a clear picture of the camera's starting state and makes it easier to diagnose unexpected behavior after parameters are modified.

python
logger.info(f"AcquisitionFrameRate: {camera.get_parameter('AcquisitionFrameRate')}")
logger.info(f"ExposureTime: {camera.get_parameter('ExposureTime')}")
logger.info(f"DeviceLinkThroughputLimit: {camera.get_parameter('DeviceLinkThroughputLimit')}")

Exposure is set to 35 ms and frame rate to 14 fps before streaming begins.

python
camera.set_parameter('ExposureTime', 35000.0)
camera.set_parameter('AcquisitionFrameRate', 14.0)

The streaming loop runs for 10 seconds using a wall-clock deadline rather than a fixed frame counter, so the actual number of frames captured depends on the configured frame rate. Each call to capture_video_color_frame switches the camera to Continuous acquisition mode on the first call — keeping the sensor running between calls — and returns one frame as a NumPy array. Each frame is then JPEG-encoded at quality 80 with cv2.imencode to reduce the data volume before being logged to Rerun as an EncodedImage, which accepts the compressed bytes directly without an intermediate decode step.

python
end_time = time.time() + 10
while time.time() < end_time:
    image = camera.capture_video_color_frame()
    if image is not None:
        _, encoded = cv2.imencode(
            '.jpg',
            image,
            [cv2.IMWRITE_JPEG_QUALITY, 80]
        )
        rr.log(
            "Continuous_Image_Capture",
            rr.EncodedImage(contents=encoded, media_type="image/jpeg")
        )

The finally block disconnects the camera exactly as in the single-image example, stopping acquisition and releasing all resources.

python
finally:
    camera.disconnect()

Run

bash
python capture_video_example.py

A Rerun viewer opens automatically. Frames stream under Continuous_Image_Capture for 10 seconds, then the camera disconnects cleanly.