Skip to Content
GuidesStream video end-to-end

Stream video end-to-end

This guide covers sending live video from a device via the Python SDK and consuming it through the WebSocket API — device to browser.

Step 1 — Send frames from the device

Install the video extras (OpenCV headless + Pillow + NumPy):

pip install "plexus-python[video]==0.7.1"

Frame by frame

Use send_video_frame() when you need frame-level control — preprocessing, annotation, or custom capture logic:

import cv2 from plexus import Plexus px = Plexus(api_key="YOUR_API_KEY", source_id="robot-01") cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if ret: px.send_video_frame(frame=frame, camera_id="front")

From a URL

Use stream_camera() to pull from an RTSP feed, HLS stream, or any URL OpenCV supports. Requires FFmpeg on $PATH:

stop = px.stream_camera(url="rtsp://192.168.1.10/stream", camera_id="front") # ... do other work ... stop.set() # stop streaming

Both methods JPEG-encode at quality=85 by default. Frames over ~750 KB are adaptively re-encoded; the gateway hard limit is 1 MB.

Step 2 — Open the video stream

Connect to the video WebSocket, send an auth frame, then receive frames:

const ws = new WebSocket( "wss://api.plexus.company/v1/sources/robot-01/video/stream?camera_id=front" ); ws.onopen = () => { ws.send(JSON.stringify({ type: "auth", api_key: "plx_..." })); }; ws.onmessage = (e) => { const msg = JSON.parse(e.data); if (msg.type === "init") { // lists which cameras are currently online console.log(msg.online_sources); } if (msg.type === "video_frame") { // msg.frame — base64 JPEG // msg.camera_id, msg.width, msg.height, msg.timestamp } };

The server sends one init frame immediately after auth, then video_frame frames as they arrive. The auth frame must be the first frame you send — the socket closes with 4001 if it doesn’t arrive within 10 seconds.

Step 3 — Render in a browser

Draw each frame onto a <canvas>:

<canvas id="feed"></canvas>
const canvas = document.getElementById("feed"); const ctx = canvas.getContext("2d"); ws.onmessage = (e) => { const msg = JSON.parse(e.data); if (msg.type === "video_frame") { const img = new Image(); img.onload = () => { canvas.width = msg.width; canvas.height = msg.height; ctx.drawImage(img, 0, 0); }; img.src = `data:image/jpeg;base64,${msg.frame}`; } };

Notes

  • Live relay only — no history, no replay. Frames are dropped silently if the consumer can’t keep up.
  • Multiple cameras — repeat the param: ?camera_id=front&camera_id=rear.
  • Timeout — add ?timeout=60 to have the server close after 60 s (code 4008). Reconnect to continue.

See Live streams for the full frame reference and close codes.

Last updated on