Capability surface

Everything a modern booth needs.

Eight years of "we should rebuild this from scratch" — finally rebuilt. Below is what's on the kiosk PC the moment you double-click the installer.

Cameras

Canon. Sony. Webcam. One interface.

Each event's capture.cameraBrand picks the primary; fallbackBrand is the resilience plan. If both fail, the always-on webcam service synthesizes frames so a session can still start.

Canon EDSDK

Tested on R100. Live view, shutter via EDSDK, file download to the PC. Operator drops the three Canon DLLs into lib/canon/ — never in the repo.

Sony Camera Remote SDK

Targets Alpha 7 IV via SDK v1.11. P/Invoke layer documented for first-deploy verification of Cr_Core.dll export names.

Webcam (OpenCvSharp4)

Any UVC device. Falls back to synthetic SkiaSharp frames if none is attached — useful for headless dev and demos.

Factory pattern

Transient lifetimes so the factory can dispose failed attempts and try the fallback cleanly. Disposed singletons don't fight retries.

Capture modes

Photo + Boomerang + GIF + AI background.

Photos go through the SkiaSharp compositor with the event's overlay PNG. Boomerang + GIF tap the camera's live view feed for a rapid burst, then encode via bundled FFmpeg (palette-optimized GIF; split / reverse / concat MP4 with libx264).

Photo

Strips or postcards, 3/4/6-up. Operator-authored overlay PNG layers on top.

Boomerang

Forward+reverse MP4, faststart-encoded for instant browser playback.

GIF

Two-pass palettegen + paletteuse. 640px wide, ~10fps.

AI background

OpenAI gpt-image-1 or Google Gemini 2.5 Flash Image. Provider chosen per preset.

Selection UI

Choose how guests pick.

Each Selection screen has its own selectionStyle. Mix and match across screens — ButtonGrid for mode picking, WheelPicker for filters, CoverFlow for premium events.

ButtonGrid

Existing visual-editor flow. Touch zones placed where the operator wants them; pressed-state PNGs supported.

WheelPicker

Horizontal swipeable carousel. Selected center scales to 1.0 with full opacity; off-center to 0.82 + 0.55 opacity. Auto-wraps.

StackedCards

Vertical scrolling list. Full-width tappable rows with descriptions. Built for accessibility / readability from distance.

CoverFlow

5 cards visible (±2 wrap). Center: scale 1.0, pink-glow drop shadow. Sides: skewed away. 280ms cubic ease-out per transition. Tap a side to bring it home; tap center to commit.

Trust + privacy

Designed to be auditable.

Three independent on-disk streams. Daily-rotated by filename — no rotation job to break. Operators can ship the audit log with the rest of the event records.

Serilog logs

14-file daily rolling. SensitiveScrubbingEnricher redacts API keys, Bearer tokens, and emails BEFORE the file sink.

Audit log (JSONL)

Consent decisions, admin sign-ins, PIN sets, API key updates, retention purges, R2 deletes. Indefinite retention.

Telemetry (opt-in)

Counters only — no PII, no slugs, no paths. Local JSONL by default; remote POST when MOCHIBOOTH_TELEMETRY_URL is set.

Deployment

Velopack installer + auto-update.

Tag a release, GitHub Actions builds + packs + creates a GitHub Release with installer + delta packages. The booth's UpdateService polls every 6h, downloads in the background, and never restarts mid-session — new bits apply on the next cold start.

6h
Update poll interval
280ms
CoverFlow ease-out
100k
Admin PIN iterations