Skip to main content
Stream video from webcams attached to the Lager Box for visual inspection, automated vision testing, and remote monitoring.

Import

Methods

Method Reference

Net.get(name, type=NetType.Webcam)

Get a webcam net by name.
Parameters: Returns: Webcam Net instance

start(box_ip)

Start a webcam video stream.
Parameters: Returns: dict with keys:
  • url - Full stream URL (e.g., http://<BOX_IP>:8086/)
  • port - Port number for the stream
  • already_running - Boolean indicating if stream was already active
Raises: RuntimeError if device is already in use or not found

stop()

Stop the webcam stream.
Returns: bool - True if stopped successfully, False if not running

get_info(box_ip)

Get information about the stream.
Parameters: Returns: dict or None - Stream info dict or None if not running. The dict has these keys:
  • url - Full stream URL
  • port - Port number for the stream
  • video_device - Video device path, such as /dev/video0
  • source - The tool that started the stream: 'api' for this Python API, 'cli' for lager webcam. None for a stream with no recorded origin.
  • started_by - The user that the starting tool named. None for a stream started from this Python API.

get_url(box_ip)

Get just the URL for the stream.
Parameters: Returns: str or None - Stream URL or None if not running

is_active()

Check if the stream is currently active.
Returns: bool - True if the stream is active, False otherwise

snapshot(raw=False)

One JPEG frame from the running stream.
The frame comes from the stream’s own capture, so it never competes with the stream, or a browser watching it, for the camera. Parameters: Returns: bytes - the JPEG Raises: RuntimeError if the stream is stopped, or has no frame within 5 seconds

frame(raw=True)

One frame from the running stream, decoded for analysis.
Parameters: Returns: numpy.ndarray - height x width x 3, in BGR order as OpenCV uses Raises: RuntimeError as snapshot() does
Use frame() in a lager python script rather than opening the camera with cv2.VideoCapture. While a stream runs it holds the camera, and a second capture of the same device gets no frames.

controls()

The camera’s image controls, each with its current value and range. Works with the stream started or stopped.
Returns: dict of control name to {"value", "min", "max", "step", "default"}, with a key only for a control the camera has. See Camera controls for the names. Three values have an auto mode: exposure, white_balance_temperature and focus. Each also has auto: True, False, or None when the camera has no auto mode for it. power_line_frequency also has options, a list of {"value", "label"}.

set_control(name, value)

Set one camera control, and keep it for this net. Works with the stream started or stopped.
Parameters: Returns: bool - True if the camera took the value Raises: ValueError for a name that is not a camera control. VideoDeviceNotFound, a RuntimeError, when the camera is not connected. controls() raises it too.

lock_controls(**overrides)

Fix every image control, for pictures that compare from frame to frame and from run to run. Turns auto exposure, auto white balance and autofocus off. Keeps every other control at its current value unless you override it. Saves them all for this net, then reads the camera back.
Parameters: Returns: dict with:
  • ok - True if every control reads back as wanted
  • controls - {name: {"wanted", "actual"}} for every control the camera has. A value outside the camera’s range is clamped, so it reads back different and ok is False
Raises: RuntimeError if the camera’s controls cannot be read; ValueError for an unknown name

Camera controls

Every range is the camera’s own. Brightness, for example, is 0 to 255 on some cameras and -64 to 64 on others. A value outside the range is clamped, and the net keeps the clamped value. A manual exposure can hold the frame rate below the mode’s. The camera still accepts the mode, so mode_error stays empty: read /api/fps for the real rate. One global-shutter camera, for example, runs about 60 fps at exposure=312 in a 90 fps mode, and about 89 fps at exposure=100. Lager changes only the controls you set. A stream start leaves the rest as the camera has them, so settings made with another tool survive it. The controls you set through set_control, lock_controls or the viewer page are kept for the net. They are put back each time its stream starts, and after the stream reopens the camera for a new mode. That also covers a camera that forgets its settings when it loses power: start the stream, or call lock_controls again.
Windows tools such as DirectShow give exposure as a power of two in seconds: -5 is 2-5 s, 31.25 ms. The Linux value is 10000 * 2**n, so -5 is exposure=312.

Examples

Start Multiple Cameras

Stream Management

Visual Inspection Test

Camera Discovery and Testing

Already Running Detection

Web Interface

Each stream serves a viewer page at its URL. It uses the same layout and colors as the oscilloscope page (lager scope NET stream web):
  • A header. Its Net picker moves to another stream on the box. It shows the camera’s model and device, and the frame rate, size and zoom. Its status is LIVE, STALLED (no frame for 3 seconds), WAITING (no frame yet) or OFFLINE (the stream does not answer)
  • The live picture, with a clock and the zoom level over it. When zoomed in, drag the picture or use the arrow keys to pan. Double-click a point to zoom in on it, or once zoomed, to centre on it
  • A sidebar with:
    • Resolution: the size and frame rate, from the modes the camera offers. If the camera cannot stream the size you pick, it keeps the old one, and the page says why. Too little USB bandwidth is one cause
    • View: zoom (slider, Out, Reset, In), Centre for the pan, Rotate (0, 90, 180 or 270 degrees) and Flip (left-right, top-bottom)
    • Focus: Auto or Manual with a distance slider, in the camera’s own range. The switch shows only on a camera with autofocus
    • Image: exposure (Auto exposure or Manual with a slider), gain and brightness. Also white balance (Auto white balance or Manual with a color temperature), and sliders for the other image controls. Each shows only on a camera that has it, with the camera’s range. While auto exposure is on, the camera sets the gain itself
    Hide sidebar hides it, and the page remembers the choice
  • Full screen shows the picture alone
  • Snapshot, which saves one frame as <net>-<timestamp>.jpg
  • At the foot of the sidebar, who started the stream, its device and its port
Every setting is kept for the net on the box. Everyone who views the stream sees the same picture, and the settings come back when the stream restarts. Larger sizes cost the box more CPU to encode: the frame rate in the header shows what the box keeps up with. On an access-gated box, when the browser’s session ends the page says SIGNED OUT and tells you to run lager webcam url for a new link.

API Endpoints

Hardware Requirements

lager nets add-all offers a net for any USB video class (UVC) camera. A model Lager has no name for is listed as UVC_Camera. HDMI capture cards are not offered as cameras. A net finds its camera again each time it starts, so it keeps working when /dev/video* numbers change.
Some cameras have no serial number, or share one with another camera on the box. Lager addresses these by USB port, as usb-port:1-1.4. Their nets follow the port: if you plug the camera into a different port, the net reports an error. The ELP global-shutter camera reports the same serial, 01.00.00, on every unit, so two on one box use port addresses.

Notes

  • A webcam net is configured by the camera’s address, its serial number or a usb-port: path. The net finds the camera’s video device from that address each time it is used
  • Streams run on ports starting from 8086
  • Each stream uses a separate port, automatically allocated
  • Streams persist until explicitly stopped or the process dies
  • Dead stream processes are automatically cleaned up
  • Only one stream can use a video device at a time
  • Default resolution is 640x480 at 30 FPS. Some cameras offer more: the ELP global-shutter camera offers 90 FPS at every size. The box re-encodes every frame, and at large sizes it can fall behind. The frame rate on the viewer page shows what it delivers
  • JPEG quality is set to 80 for bandwidth/quality balance
  • Streams are reachable over HTTP at the Lager Box IP address. On an access-gated box, a request needs a sign-in token, and the url from start() carries none. Use lager webcam url for a link that carries your token
  • Zoom is digital (crop and scale), not optical