resolve_device now prints each by-id candidate it scans, which entry matched, and the resolved device path; the no-match error lists all by-id entries with their targets. Camera startup logs the raw config setting, resolved path, the node's sysfs name, the OpenCV version, and the negotiated resolution. 'python3 camera.py' now dumps every detected camera before opening, to troubleshoot machines where the wrong camera gets used.
131 lines
4.7 KiB
Markdown
131 lines
4.7 KiB
Markdown
# CRT Photobooth
|
||
|
||
A fullscreen photobooth for a Linux laptop mirrored to a 4:3 CRT. Guests press
|
||
the button (any mouse button) to take a 3-photo shoot with countdowns and
|
||
flashes. After 4 shoots, all 12 photos are printed on one contact sheet.
|
||
When idle for 5 minutes, a fish-tank screensaver protects the CRT from burn-in.
|
||
|
||
## Setup on a new laptop
|
||
|
||
1. **Install Python 3.11 or newer** (check with `python3 --version`).
|
||
|
||
2. **Install the dependencies:**
|
||
|
||
```bash
|
||
pip install pygame-ce opencv-python pillow
|
||
```
|
||
|
||
Note: it's `pygame-ce`, not `pygame` — the community edition has wheels
|
||
for newer Python versions. If pip refuses because the system Python is
|
||
"externally managed", either use `pip install --user ...` or create a
|
||
virtual environment:
|
||
|
||
```bash
|
||
python3 -m venv ~/photobooth-venv
|
||
~/photobooth-venv/bin/pip install pygame-ce opencv-python pillow
|
||
# then run with: ~/photobooth-venv/bin/python photobooth.py
|
||
```
|
||
|
||
3. **Plug in the Macally webcam** and confirm Linux sees it:
|
||
|
||
```bash
|
||
ls /dev/v4l/by-id/
|
||
```
|
||
|
||
You should see something like `usb-SolidYear_Macally_USB2.0Camera-video-index0`.
|
||
The default config finds it automatically by name.
|
||
|
||
4. **Set up the printer.** The booth prints via CUPS with the `lp` command.
|
||
Check what's configured and set a default:
|
||
|
||
```bash
|
||
lpstat -p # list printers
|
||
lpoptions -d NAME # set the default printer
|
||
lpstat -p -d # verify: should show a default destination
|
||
```
|
||
|
||
Print a test page from the printer settings GUI to make sure it works
|
||
before an event.
|
||
|
||
5. **Copy this whole folder** to the laptop and run it:
|
||
|
||
```bash
|
||
python3 photobooth.py
|
||
```
|
||
|
||
Add `--windowed` to test in a window instead of fullscreen.
|
||
**Press Esc or Q to quit.**
|
||
|
||
## Customizing
|
||
|
||
- **All settings** live in `config.toml` — camera choice, screen text,
|
||
countdown lengths, screensaver timeout, printer options. Comments in the
|
||
file explain each one.
|
||
- **Idle screen background:** replace `assets/background.png` (any size,
|
||
it gets scaled to the screen — 4:3 looks best, e.g. 800×600).
|
||
- **Fish:** drop your fish drawings into the `fish/` folder as PNGs with
|
||
transparent backgrounds. Draw them **facing right** — the program flips
|
||
them automatically when they swim left. Bubbles come out of the front
|
||
(mouth) end. Delete `placeholder_fish.png` once you have real fish.
|
||
|
||
## Switching cameras
|
||
|
||
In `config.toml`, `device = "auto-macally"` finds the Macally cam by name.
|
||
To use a different camera:
|
||
|
||
- `device = "auto-integrated"` — match another camera by (partial) name
|
||
from `ls /dev/v4l/by-id/`, case-insensitive
|
||
- `device = "/dev/video2"` — an exact device path
|
||
- `device = "0"` — a plain index
|
||
|
||
## Where things go
|
||
|
||
- `photos/` — individual shots for the current print cycle. Deleted
|
||
automatically after a successful print. (If the program is restarted
|
||
mid-cycle, photos here are counted so no progress is lost.)
|
||
- `contact_sheets/` — every printed sheet, kept as a backup in case of
|
||
printer trouble. Delete them manually now and then, or set
|
||
`delete_contact_sheets = true` in the config to remove each one right
|
||
after it prints.
|
||
|
||
## If printing fails
|
||
|
||
The booth doesn't lose anything: the contact sheet is saved in
|
||
`contact_sheets/`, an error shows on the idle screen, and you can print the
|
||
sheet by hand with:
|
||
|
||
```bash
|
||
lp -o media=letter -o fit-to-page contact_sheets/sheet_XXXX.jpg
|
||
```
|
||
|
||
Common causes: printer off or unplugged (`lpstat -p` says "disabled" —
|
||
re-enable with `cupsenable PRINTER_NAME`), or no default printer set.
|
||
|
||
## Troubleshooting the camera
|
||
|
||
Test the camera on its own (uses the device from `config.toml`):
|
||
|
||
```bash
|
||
python3 camera.py
|
||
```
|
||
|
||
It first prints a pre-flight dump of every camera the system sees
|
||
(`/dev/v4l/by-id/` names, device nodes, and what each node identifies as),
|
||
then reports which device was matched, resolved, and opened, plus the OpenCV
|
||
version. If the booth ever uses the wrong camera, run this and read the
|
||
output — it shows exactly where the selection went sideways.
|
||
|
||
**If it reports black frames** (or the live preview shows a warning): the
|
||
Macally cam's chipset sometimes wedges and streams pure black until it is
|
||
power-cycled. **Unplug the camera, plug it back in, and restart the
|
||
program.** Worth doing a quick test shoot at the start of an event.
|
||
|
||
## Heads-up
|
||
|
||
- The Brother HL-5470DW is a **monochrome laser** — contact sheets print
|
||
in black & white.
|
||
- The live preview is mirrored (like a mirror) so posing feels natural, but
|
||
saved photos are not mirrored. Set `mirror_preview = false` to change that.
|
||
- CRT overscan may crop the very edges of the screen; once the CRT is
|
||
connected, adjust text positions/sizes in code or the CRT's own controls.
|