2026-07-18 15:17:37 -04:00
2026-07-18 15:17:37 -04:00
2026-07-18 15:17:37 -04:00
2026-07-18 15:17:37 -04:00
2026-07-18 15:17:37 -04:00
2026-07-18 15:17:37 -04:00
2026-07-18 15:17:37 -04:00
2026-07-18 15:17:37 -04:00
2026-07-18 15:17:37 -04:00

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:

    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:

    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:

    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:

    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:

    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:

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):

python3 camera.py

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.
Description
No description provided
Readme 100 KiB
Languages
Python 100%