camshooter 0.1.1

Select a webcam, preview the live stream, and grab PNG snapshots with a keypress.
camshooter-0.1.1 is not a library.

camshooter

A Linux GUI tool to select a webcam, preview its live video stream, and save PNG snapshots with a keyboard shortcut.

camshooter is a single, self-contained process — no daemon, no IPC. Pick a camera, watch the live preview, and hit a key to grab a timestamped PNG.

Features

  • Lists available webcams via V4L2 and lets you pick one.
  • Live video preview of the selected camera.
  • One-key PNG snapshots with timestamped filenames.
  • Never overwrites: same-second collisions get a -N suffix (configurable).
  • Configurable output directory, filename prefix, and collision behavior.
  • CLI override for the output directory.

Requirements

  • Linux (Fedora 44 tested; Linux only for now).
  • A V4L2-compatible webcam exposed at /dev/video*.
  • The Rust toolchain (edition 2024).
  • clang / llvm — nokhwa's V4L backend uses bindgen.

On Fedora, install the build dependencies:

sudo dnf install clang clang-devel llvm-devel

libv4l-devel is not required.

Camera access

The active Fedora desktop session usually grants access to /dev/video* through logind ACLs. If camshooter reports "No webcams detected", add yourself to the video group and re-login:

sudo usermod -aG video $USER

Build & Run

Build a release binary:

cargo build --release

Run it:

cargo run
# or
./target/release/camshooter

Save snapshots to a specific directory (created if missing):

camshooter -o ~/Pictures/cam

Usage

  1. Launch camshooter. A window lists the available webcams.
  2. Pick a camera: click it, or press a number key 19.
  3. The live preview appears. Use the keybindings below.

Keybindings

Key Action
19 Select camera (picker)
Space or S Take a snapshot
Esc Back to the camera picker
Q Quit

Snapshot filenames

Snapshots are named snapshooter{ddMMyyHHmmss}.png using a 24-hour clock — for example, a capture on 6 June 2026 at 14:30:12 becomes:

snapshooter060626143012.png

If a file with that name already exists (a same-second collision), camshooter appends a -N suffix (snapshooter060626143012-1.png, and so on). It never overwrites an existing file unless on_collision = "overwrite" is set in the config.

Configuration

Configuration is optional. camshooter reads ~/.config/camshooter/config.toml (respecting $XDG_CONFIG_HOME). If the file is missing, built-in defaults are used. All keys are optional:

output_dir = "~/Pictures/cam"   # default save dir; overridden by -o
prefix = "snapshooter"           # filename prefix
on_collision = "suffix"          # "suffix" | "overwrite"

Output directory precedence

The output directory is resolved in this order (lowest to highest priority):

  1. Built-in default — the current directory.
  2. output_dir in config.toml.
  3. The -o / --output flag.

Project structure

src/
  main.rs       CLI parsing + bootstrap
  config.rs     TOML config loading
  capture.rs    camera capture thread
  ui.rs         egui application
  snapshot.rs   PNG saving

Built with nokhwa (V4L2 capture), eframe / egui (window and GUI), image (PNG encoding), clap (CLI), chrono (timestamps), and serde / toml (config).

Testing

Run the test suite:

cargo test

The snapshot filename/collision logic and config parsing are unit-tested and run without any camera hardware.

Known limitations

  • A camera entry may show a black preview. Many UVC webcams expose more than one /dev/video* node (e.g. a second metadata-only node), so the same camera can appear twice in the picker — and one of those entries can stream black/empty frames. If the preview is black, go Back (Esc) and pick the other entry. Captured snapshots reflect exactly what the preview shows. Smarter node filtering is planned.
  • Linux/V4L2 only for now.

License

Licensed under the Apache License 2.0.