Back to McPics

Behind the slideshow

A slideshow
seemed simple.

Getting photos onto the TV seemed like the hard part. It turned out that choosing which picture came next, handling emailed attachments, and keeping everything running from a distance took just as much attention.

01 / A photo's journey

From email
to the TV.

McPics runs on a Linux Mint computer connected to the display. A local web app, an email importer, and a small database each handle a different part of the job.

  1. The family sends a photo

    Pictures arrive by email. Nobody needs to create an account on this website or learn a new app.

  2. The importer prepares it

    A scheduled process checks the mailbox, filters attachments, converts iPhone formats when needed, and checks for duplicates.

  3. The computer keeps it

    Photos stay on the computer. A database records who sent them, which ones are duplicates, and when they last appeared.

  4. The slideshow displays it

    The local app chooses the next photo. A fullscreen browser loads it, fits the whole image on screen, and handles the transition.

This website doesn't run the slideshow. It provides the instructions and email address. Importing and playback happen on the display computer, so photos already there can keep playing without internet access. New email still needs a connection.

02 / What got complicated

What needed
another try.

Getting a picture on screen was only the start. These six problems took some figuring out as the project grew.

“Fair” rotation wasn't actually fair.

Older photos had built up hundreds of appearances. Trying to equalize lifetime counts made a fresh batch play over and over to catch up, crowding out the rest of the collection.

Photo selection now puts more weight on how long it has been since a photo appeared, with a limit on how much its lifetime count can influence the choice. Unseen photos get priority, while new arrivals get a brief spotlight.

Recent-repeat exclusions help spread things out. An optional sender-balanced mode adds variety, too. It's a weighted selection, not a promise that every photo will play exactly once before anything repeats.

Similar photos aren't always duplicates.

Two different shots from a quick burst were similar enough to land in the same duplicate group. One disappeared from the rotation, and the contribution count was wrong.

Stricter visual matching makes separate shots less likely to be grouped together. Exact copies are checked with a file fingerprint; similar-looking copies use a separate perceptual fingerprint.

When copies do belong together, McPics prefers the version with the most pixels and can preserve credit for the people who sent it.

Stricter matching protects distinct photos, but can let some near-duplicate resends through. That tradeoff matters when two similar pictures are both worth keeping.

An email attachment isn't always a usable photo.

Phones can shrink pictures before sending them. iPhone photos may arrive in HEIC format. Email signatures add tiny logos, while real photos sometimes arrive marked as inline images.

The importer now checks filenames, attachment types, file size, and image dimensions. It converts HEIC/HEIF photos to JPEG for the browser and keeps low-resolution imports out of the rotation without deleting them.

Optional replies confirm successful imports or flag undersized photos and emails with no photos attached. Thank-you replies are grouped after a quiet period, so sending several pictures doesn't produce a reply for every attachment.

A retry could get stuck in the same place.

The importer kept rereading old messages. If the mailbox hit a quota limit partway through, the next run could hit the same limit before it ever reached new photos.

The importer now saves its place after each fully processed message, using the mailbox's stable message identifiers. The next run resumes there, and saved attachment fingerprints help avoid importing the same files again.

Each display computer tracks its own progress. It doesn't depend on an email's read/unread flag, which another device or someone checking the inbox could change.

A smooth fade took more than a fade effect.

Changing a single image could create a jump through black. Captions could arrive before their photo, and a file that failed to load could interrupt the experience.

Two image layers let the next photo load before the current one fades away. Captions update after the transition, and an image that fails to load is logged and skipped.

The layout fits the whole photo on screen without cropping. It also scales for larger displays and hides the mouse pointer when it's idle.

Turning off the screen changed the desktop.

Display changes can move windows and interfere with remote support. Simply putting the whole computer to sleep would also stop it from collecting new pictures.

The mini-PC setup uses separate outputs for the slideshow screen and remote support. A dummy HDMI adapter keeps a display available for remote access even when the TV is off.

The optional sleep schedule turns off only the slideshow output, leaving the app and importer running. When it wakes, the system restores the display layout and opens a fresh fullscreen browser on the right screen.

03 / Under the hood

The pieces
that run it.

For anyone interested in the software, here's what each part does.

ComponentIts job
Linux MintThe desktop environment on the display computer.
Python + FlaskThe local web app, settings interface, photo-serving routes, and next-photo selection.
SQLitePersistent import progress, photo metadata, duplicate groups, contributor records, settings, and rotation history.
IMAP + SMTPRetrieving photo emails and sending optional acknowledgments or quality notices.
Image toolsPillow and ImageHash help inspect and compare images. heif-convert prepares HEIC/HEIF attachments for browser playback.
Fullscreen browserThe slideshow and Family Update screen. Firefox is preferred when installed, with Chromium-based browser fallbacks.
systemd + display toolsUser services and timers keep the app and importer separate. xrandr handles display layout and output power; wmctrl helps place and manage the kiosk window.

Starting in the right order

The app starts independently. The login launcher waits for remote support and the app's health check before opening the fullscreen browser. Dependency installation stays out of everyday startup.

Checking it from a distance

Desktop shortcuts, local settings, health checks, and logs make problems easier to diagnose without asking Grandma to troubleshoot the computer.

All that work,
so she can just enjoy the pictures.

The project grew, but the goal hasn't changed: family sends pictures, and Grandma gets to see them.

Back to the family story