A virtual photobooth, take shots, apply effects, download your strip
No install needed. Open in your browser, allow camera access, and start shooting. β¨
SnapBooth is a browser-based virtual photobooth built with Streamlit. It captures a series of photos from the user's webcam, lets them choose a layout, apply filters and stickers, composes everything into a polished strip or grid, and exports it as a high-resolution JPG or print-ready PDF.
- 9 layout options β 1Γ3, 1Γ4, 1Γ6 strips and 2Γ2, 2Γ3, 2Γ4, 3Γ2, 3Γ3, 4Γ2 grids
- 23 frame styles β Classic, Film Strip, Pink Heart, Garden, Blue Sky, Vintage, Neon Glow, Lavender, Midnight, Cherry Blossom, Gold Foil, Ocean Wave, Galaxy, Rose Gold, Pastel Dream, Autumn, Mint Fresh, Black & Gold, Sakura, Electric Blue, Warm Sunset, Ice Crystal, Purple Rain
- 23 image filters β Original, B&W, Sepia, Retro, Cool, Vivid, Soft, Warm, Fade, β¨ Golden, πΈ Cherry, ποΈ Film, β‘ Neon, π¬ Pastel, π Moody, πΏ Y2K, π΅ Matcha, π Lavender, π Crisp, π Dusk, πΌ Tokyo, π©· Candy, π· Polaroid
- 12 sticker themes β Hearts, Stars, Flowers, Sparkles, Clovers, Butterflies, Diamonds, Bows, Crowns, Bubbles, Confetti (all PIL-drawn, no dependencies)
- HD strip compositor β renders at 2Γ resolution internally, downscaled for crisp anti-aliased output
- Dual export β download as JPEG (quality 96, 4:4:4 chroma) or PDF (ReportLab A4, print-ready)
- Mobile block β detects phones/tablets via JS and shows a polished "use desktop" overlay
- All in-memory β no files written to disk; camera data never leaves the session
# Clone
git clone https://github.com/evan-william/snapbooth.git
cd snapbooth
# Install dependencies (Python 3.10+ recommended)
pip install -r requirements.txt
# Launch
streamlit run app.pychmod +x run_tests.sh
./run_tests.sh # standard run
./run_tests.sh --coverage # with HTML coverage reportThe app is a four-stage flow managed by Streamlit's session state:
[ Layout + Frame ] β [ Camera Capture ] β [ Preview & Effects ] β [ Download ]
Each stage is an independent render function. All state transitions go through
core/session.py, which is the single source of truth for reads and writes to
st.session_state.
Key technical detail β processed photos are stored as JPEG bytes, not PIL Image objects.
PIL objects expire from Streamlit's in-memory media cache between reruns, causing
MediaFileHandler errors and visible flickering. Bytes survive st.session_state
serialization perfectly and are converted back to PIL only when compositing is needed.
snapbooth/
βββ app.py # Entry point & stage router
βββ requirements.txt
βββ run_tests.sh # Test runner script
βββ .streamlit/
β βββ config.toml # Theme configuration
βββ config/
β βββ settings.py # Constants, layout/frame/filter/sticker configs
βββ core/
β βββ validation.py # Magic-byte image validation
β βββ filters.py # PIL + NumPy filter pipeline (23 filters)
β βββ stickers.py # PIL-drawn themed sticker overlays
β βββ compositor.py # HD strip/grid layout engine (2Γ render)
β βββ exporter.py # JPG + ReportLab PDF export
β βββ session.py # Streamlit session state helpers
βββ ui/
β βββ styles.py # Global CSS injection
β βββ mobile_block.py # JS mobile detection + block overlay
β βββ template_page.py # Stage 1 β layout + frame selection
β βββ camera_page.py # Stage 2 β sequential photo capture
β βββ preview_page.py # Stage 3 β filter/sticker/frame tuning
β βββ download_page.py # Stage 4 β strip display + download
βββ tests/
βββ test_validation.py
βββ test_filters.py
βββ test_compositor.py
βββ test_exporter.py
| Layer | Technology |
|---|---|
| UI framework | Streamlit |
| Image processing | Pillow, NumPy |
| PDF generation | ReportLab |
| Testing | pytest, pytest-cov |
| Key | Name | Photos |
|---|---|---|
1x3 |
1 Γ 3 Strip | 3 |
1x4 |
1 Γ 4 Strip | 4 |
1x6 |
1 Γ 6 Strip | 6 |
2x2 |
2 Γ 2 Grid | 4 |
2x3 |
2 Γ 3 Grid | 6 |
2x4 |
2 Γ 4 Grid | 8 |
3x2 |
3 Γ 2 Grid | 6 |
3x3 |
3 Γ 3 Grid | 9 |
4x2 |
4 Γ 2 Grid | 8 |
- Magic-byte validation β camera images are validated by their actual bytes, not file extension, before entering any processing pipeline.
- Size cap β each captured frame is rejected if it exceeds 10 MB.
- No disk writes β all image data lives exclusively in
st.session_state(in-memory bytes). Nothing is persisted between sessions. - No user data stored β the app has no database, no authentication, and no logging of image content.
- Multiple layout options (strips + grids)
- Aesthetic filter collection (23 filters)
- Themed sticker overlays (12 themes, PIL-drawn)
- HD output (2Γ internal render + sharpness pass)
- Mobile block screen
- Timer countdown before each shot
- Custom text overlay on strip header/footer
- Background removal (via
rembg) - Streamlit Cloud deployment β snapbooth.streamlit.app
- Fork the repository
- Create a feature branch (
git checkout -b feature/your-feature) - Commit your changes (
git commit -m 'Add your feature') - Push and open a Pull Request
Please ensure run_tests.sh passes before submitting.
Distributed under the MIT License. See LICENSE for details.
Built by Evan William Β· Β© 2026 SnapBooth Β· All rights reserved