IDS: Publish Live Video with BabyROS
SUMMARY
Stream live video using BabyROS as the communication layer. Two scripts share responsibility: a camera server that owns the hardware connection, and a client that controls streaming remotely via BabyROS topics.
Example
The camera server (camera_loop.py) runs in Terminal 1 — it connects to the hardware and keeps BabyROS nodes alive. The client (publish_video_example.py) runs in Terminal 2 — it publishes a start signal, subscribes to the video topic to receive and log frames to Rerun, then publishes a stop signal after 10 seconds.
Code
Terminal 1 — Camera Server:
"""
Camera loop for the IDS camera.
"""
import time
from loguru import logger
from babyros import node
from medulla.cameras import ids
def main():
camera = None
try:
camera = ids.IDS(
name="my_ids_camera",
serial_number="4108909352"
)
camera.connect()
logger.info("Camera Server is running... Press Ctrl+C to stop.")
while True:
time.sleep(1)
except KeyboardInterrupt:
logger.info("Shutting down server...")
finally:
if camera is not None:
camera.disconnect()
node.SessionManager.delete()
logger.info("Completed cleanup.")
if __name__ == "__main__":
main()Terminal 2 — BabyROS Client:
"""
Stream live video from an IDS camera over BabyROS.
"""
import time
from loguru import logger
import rerun as rr
import numpy as np
from babyros import node
def log_video(data: np.ndarray) -> None:
rr.log(
"Continuous_Image_Capture",
rr.EncodedImage(contents=data, media_type="image/jpeg")
)
def main():
rr.init("IDS_Example", spawn=True)
name = "my_ids_camera"
base_topic = f"medulla/v1/camera/ids/IDS/{name}"
start_video_stream_publisher = node.Publisher(
topic=f"{base_topic}/start_video_stream"
)
stop_video_stream_publisher = node.Publisher(
topic=f"{base_topic}/stop_video_stream"
)
video_subscriber = node.Subscriber(
topic=f"{base_topic}/video",
callback=log_video,
)
try:
start_video_stream_publisher.publish(data={})
time.sleep(10)
stop_video_stream_publisher.publish(data={})
except KeyboardInterrupt:
logger.info("Shutting down.")
finally:
start_video_stream_publisher.delete()
stop_video_stream_publisher.delete()
video_subscriber.delete()
node.SessionManager.delete()
logger.info("Completed cleanup.")
if __name__ == "__main__":
main()Explanation
Now, let’s break down the code piece by piece.
Camera Server (camera_loop.py)
The server creates an IDS instance and connects to the hardware. After connecting, it enters an infinite sleep loop — this does nothing except keep the process, and the BabyROS nodes registered inside the IDS instance, alive and reachable by remote clients.
camera = ids.IDS(
name="my_ids_camera",
serial_number="4108909352"
)
camera.connect()
while True:
time.sleep(1)On Ctrl+C, the finally block disconnects the camera and calls node.SessionManager.delete() to cleanly tear down the BabyROS session.
finally:
if camera is not None:
camera.disconnect()
node.SessionManager.delete()BabyROS Client (publish_video_example.py)
The client never accesses the camera hardware directly. Instead it constructs three BabyROS nodes whose topic paths mirror those registered by the IDS instance in the server process. The name variable must exactly match the name passed to IDS in the server, because both sides derive their topic paths from it.
name = "my_ids_camera"
base_topic = f"medulla/v1/camera/ids/IDS/{name}"
start_video_stream_publisher = node.Publisher(topic=f"{base_topic}/start_video_stream")
stop_video_stream_publisher = node.Publisher(topic=f"{base_topic}/stop_video_stream")
video_subscriber = node.Subscriber(topic=f"{base_topic}/video", callback=log_video)Publishing an empty payload to start_video_stream signals the server to begin continuous acquisition. The server JPEG-encodes each incoming frame and pushes it onto the video topic. Each frame arrives in the log_video callback and is forwarded to Rerun using rr.EncodedImage, which accepts the compressed bytes directly without an intermediate decode step. After 10 seconds, publishing to stop_video_stream halts acquisition on the server side.
start_video_stream_publisher.publish(data={})
time.sleep(10)
stop_video_stream_publisher.publish(data={})The finally block deletes all three nodes and closes the BabyROS session regardless of how the script exits.
finally:
start_video_stream_publisher.delete()
stop_video_stream_publisher.delete()
video_subscriber.delete()
node.SessionManager.delete()Run
Start the server first, then the client. Both must run from a terminal.
Terminal 1:
python camera_loop.pyWait for Camera Server is running... Press Ctrl+C to stop., then:
Terminal 2:
python publish_video_example.pyFrames stream under Continuous_Image_Capture for 10 seconds. Press Ctrl+C in Terminal 1 to shut down the server.

