camshooter 0.1.2

Select a webcam, preview the live stream, and grab PNG snapshots with a keypress.
# 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:

```sh
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:

```sh
sudo usermod -aG video $USER
```

## Build & Run

Build a release binary:

```sh
cargo build --release
```

Run it:

```sh
cargo run
# or
./target/release/camshooter
```

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

```sh
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 `1``9`.
3. The live preview appears. Use the keybindings below.

### Keybindings

| Key            | Action                    |
| -------------- | ------------------------- |
| `1``9`        | 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:

```toml
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:

```sh
cargo test
```

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

## Known limitations

- **Linux/V4L2 only** for now.

> Webcams used to appear twice in the picker because a single UVC camera exposes both a
> video-capture and a metadata `/dev/video*` node (the latter streamed black frames). The
> picker now probes each node's V4L2 capabilities and lists only true capture nodes.

## License

Licensed under the [Apache License 2.0](LICENSE).