egui-cameras 0.3.1

egui / eframe integration for the cameras crate. Wraps a cameras::pump::Pump into an egui TextureHandle so you can render live camera frames as an egui::Image with a few lines of glue.
Documentation

egui-cameras is the egui integration for cameras, a cross-platform camera library for Rust. It owns the thin glue between a running cameras::pump::Pump and an egui::TextureHandle, so you can render live camera frames as an egui::Image with a few lines of code.

Every camera-side primitive (pause / resume pump, single-frame capture, unified CameraSource, hotplug monitor) lives upstream in cameras itself and is re-exported from this crate as egui_cameras::cameras, so a single dependency is enough.

Quick Start

[dependencies]

egui-cameras = "0.1"

eframe = "0.32"

use egui_cameras::cameras::{self, PixelFormat, Resolution, StreamConfig};
use eframe::egui;

struct App {
    stream: egui_cameras::Stream,
}

impl App {
    fn new() -> Result<Self, cameras::Error> {
        let devices = cameras::devices()?;
        let device = devices.first().ok_or(cameras::Error::DeviceNotFound("no cameras".into()))?;
        let config = StreamConfig {
            resolution: Resolution { width: 1280, height: 720 },
            framerate: 30,
            pixel_format: PixelFormat::Bgra8,
        };
        let camera = cameras::open(device, config)?;
        Ok(Self { stream: egui_cameras::spawn(camera) })
    }
}

impl eframe::App for App {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui_cameras::update_texture(&mut self.stream, ctx).ok();
        egui::CentralPanel::default().show(ctx, |ui| {
            egui_cameras::show(&self.stream, ui);
        });
        ctx.request_repaint();
    }
}

What's in the box

Item Purpose
Stream Bundle of a Pump + Sink + TextureHandle. Holds everything one live camera needs.
Sink Shared slot the pump writes each frame into. Cheap to clone.
spawn(camera) -> Stream Convenience: spawn a pump and wire it to a fresh Stream with a default texture name.
spawn_named(camera, name) -> Stream Like spawn, but lets you name the texture (useful for multi-camera apps).
spawn_pump(camera, sink) -> Pump Lower-level: spawn a pump that writes into your own Sink.
publish_frame(sink, frame) Write a frame into a sink (for custom pump code).
take_frame(sink) -> Option<Frame> Pull the latest frame out of a sink.
frame_to_color_image(frame) Convert a cameras Frame into an egui::ColorImage.
update_texture(stream, ctx) Upload the latest frame to the stream's texture. Call each update tick.
show(stream, ui) Draw the texture as an egui::Image scaled to fit the available area.

Pump controls (set_active, capture_frame, stop_and_join) are re-exported directly from cameras::pump.

Pause + snapshot

Pause the pump when the user isn't looking, grab fresh frames on demand without closing the camera.

use egui_cameras::{capture_frame, set_active};

// Park the pump (no per-frame Rust work; camera stays open):
set_active(&stream.pump, false);

// Grab a fresh snapshot regardless of pause state:
let frame = capture_frame(&stream.pump);

Features

Feature Default Description
rtsp off Forwards to cameras/rtsp; enables CameraSource::Rtsp on macOS and Windows.
discover off Forwards to cameras/discover; enables the DiscoveryWidget for scanning a subnet for Axis RTSP cameras.

Discovery

With the discover feature, start_discovery(config) returns a DiscoverySession. Call poll_discovery(&mut session) each frame; it is non-blocking and safe to call infrequently (the underlying channel is unbounded). Render results with either the bundled show_discovery(&session, ui), or the split helpers show_discovery_status + show_discovery_results when you want the status and result list in different UI locations. A click yields a DiscoveredCamera that can be passed to cameras::open_source. Drop the session (or call cancel_discovery(session)) to cancel the scan.

DiscoverySession's observable fields are public: cameras, unmatched_hosts: Vec<(IpAddr, String)>, scanned, total, done. The underlying Discovery handle is intentionally private so callers cannot accidentally steal events from poll_discovery's drain path.

Configs mix CIDR subnets and explicit host:port endpoints, so port-forwarded tunnels work alongside a LAN scan. The apps/egui-demo Discover panel accepts comma-separated CIDRs and/or host:port entries in its Targets field.

Versioning

egui-cameras pins a specific minor version of cameras via pub use cameras;, so installing egui-cameras = "0.1" gives you a compatible cameras automatically.

Example

A runnable example lives at apps/egui-demo in the repository: live preview, pause toggle, take-picture button.

License

Dual-licensed under MIT or Apache-2.0 at your option.