v1.4.1 — Shared Albums #2

Merged
jessikitty merged 30 commits from dev into main 2026-06-09 16:20:26 +10:00
Showing only changes of commit 39aff8c839 - Show all commits
+203 -1
View File
@@ -1 +1,203 @@
IyBGcmFtYmUKCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgc3JjPSJwdWJsaWMvaW1nL2ljb24ucG5nIiBhbHQ9IkZyYW1iZSIgd2lkdGg9IjE4MCI+CjwvcD4KCkEgbGlnaHR3ZWlnaHQsIHNlbGYtY29udGFpbmVkIERvY2tlciB3ZWIgYXBwbGljYXRpb24gdGhhdCBjb25uZWN0cyB0byB5b3VyIFtJbW1pY2hdKGh0dHBzOi8vaW1taWNoLmFwcC8pIHNlcnZlciBhbmQgZGlzcGxheXMgcGhvdG9zIGluIGEgYmVhdXRpZnVsIGZ1bGwtc2NyZWVuIHNsaWRlc2hvdyDigJQgcGVyZmVjdCBmb3IgdHVybmluZyBvbGQgdGFibGV0cywgc3BhcmUgc2NyZWVucywgYW5kIFJhc3BiZXJyeSBQaXMgaW50byBkaWdpdGFsIHBob3RvIGZyYW1lcy4KCiMjIOKcqCBGZWF0dXJlcwoKLSAqKkltbWljaCBBUEkgSW50ZWdyYXRpb24qKiDigJQgQ29ubmVjdHMgc2VjdXJlbHkgdmlhIEFQSSBrZXkgKGtlcHQgc2VydmVyLXNpZGUpCi0gKipBbGJ1bSBCcm93c2VyKiog4oCUIFNlbGVjdCBhbnkgYWxidW0sIHJhbmRvbSBwaG90b3MsIG9yIGZhdm9yaXRlcyBvbmx5Ci0gKipQZXJzb24gLyBGYWNlIFN1cHBvcnQqKiDigJQgRGlzcGxheSBwaG90b3Mgb2YgYSBzcGVjaWZpYyBwZXJzb24gdmlhIEltbWljaCdzIGZhY2UgcmVjb2duaXRpb24KLSAqKkFkbWluIERhc2hib2FyZCoqIOKAlCBSZWFsLXRpbWUgV2ViU29ja2V0LWJhc2VkIGNvbnRyb2wgcGFuZWwgZm9yIGFsbCBjb25uZWN0ZWQgZnJhbWVzCi0gKipBZG1pbiBBdXRoZW50aWNhdGlvbioqIOKAlCBPcHRpb25hbCB1c2VybmFtZS9wYXNzd29yZCBsb2dpbiB0byBwcm90ZWN0IHRoZSBhZG1pbiBkYXNoYm9hcmQKLSAqKlJFU1QgQVBJIHdpdGggVG9rZW4gQXV0aCoqIOKAlCBDb250cm9sIGZyYW1lcyBmcm9tIEhvbWUgQXNzaXN0YW50LCBzY3JpcHRzLCBvciBleHRlcm5hbCB0b29scwotICoqVVJMLUJhc2VkIFplcm8tVG91Y2ggTGF1bmNoKiog4oCUIFNraXAgdGhlIHNldHVwIHNjcmVlbiBlbnRpcmVseSB3aXRoIHF1ZXJ5IHBhcmFtZXRlcnMKLSAqKkF1dG8tUmVmcmVzaCoqIOKAlCBQZXJpb2RpY2FsbHkgY2hlY2tzIGZvciBuZXcgcGhvdG9zIGFkZGVkIHRvIHRoZSBzb3VyY2UgYWxidW0vcGVyc29uCi0gKipTbW9vdGggQ3Jvc3NmYWRlKiog4oCUIERvdWJsZS1idWZmZXJlZCBpbWFnZSB0cmFuc2l0aW9ucyB3aXRoIGNvbmZpZ3VyYWJsZSBkdXJhdGlvbgotICoqQmFja2dyb3VuZCBCbHVyKiog4oCUIEJsdXJyZWQgYmFja2Ryb3AgZmlsbHMgdGhlIHNwYWNlIGJlaGluZCBub24tY292ZXJpbmcgaW1hZ2VzCi0gKipDbG9jayAmIERhdGUgT3ZlcmxheSoqIOKAlCBBbHdheXMga25vdyB0aGUgdGltZSBhdCBhIGdsYW5jZQotICoqRVhJRiBJbmZvKiog4oCUIFNob3dzIHBob3RvIGxvY2F0aW9uLCBkYXRlLCBhbmQgY2FtZXJhIGluZm8KLSAqKlByb2dyZXNzIEJhcioqIOKAlCBTdWJ0bGUgaW5kaWNhdG9yIG9mIHRpbWUgdW50aWwgbmV4dCBwaG90bwotICoqVG91Y2ggQ29udHJvbHMqKiDigJQgVGFwIGxlZnQvcmlnaHQgZWRnZXMgdG8gbmF2aWdhdGUsIGNlbnRyZSB0byB0b2dnbGUgb3ZlcmxheQotICoqS2V5Ym9hcmQgQ29udHJvbHMqKiDigJQgQXJyb3cga2V5cywgU3BhY2UsIEYgKGZ1bGxzY3JlZW4pLCBJIChpbmZvKSwgRXNjIChleGl0KQotICoqU2NyZWVuIFdha2UgTG9jayoqIOKAlCBQcmV2ZW50cyBzY3JlZW4gc2xlZXAgb24gc3VwcG9ydGVkIGRldmljZXMKLSAqKlJlc3BvbnNpdmUqKiDigJQgV29ya3Mgb24gYW55IHNjcmVlbiBzaXplIGZyb20gcGhvbmUgdG8gVFYKLSAqKk9sZGVyIERldmljZSBGcmllbmRseSoqIOKAlCBWYW5pbGxhIEhUTUwvQ1NTL0pTLCBubyBoZWF2eSBmcmFtZXdvcmtzCi0gKipEb2NrZXIgQ29udGFpbmVyaXNlZCoqIOKAlCBTaW5nbGUgY29udGFpbmVyLCBtaW5pbWFsIGZvb3RwcmludAoKIyMg8J+agCBRdWljayBTdGFydAoKIyMjIDEuIEdldCB5b3VyIEltbWljaCBBUEkgS2V5CgoxLiBPcGVuIHlvdXIgSW1taWNoIHdlYiBpbnRlcmZhY2UKMi4gQ2xpY2sgeW91ciBwcm9maWxlIHBpY3R1cmUg4oaSICoqQWNjb3VudCBTZXR0aW5ncyoqIOKGkiAqKkFQSSBLZXlzKioKMy4gQ3JlYXRlIGEgbmV3IGtleSB3aXRoIGBhc3NldC5yZWFkYCBhbmQgYGFsYnVtLnJlYWRgIHBlcm1pc3Npb25zCgojIyMgMi4gUnVuIHdpdGggRG9ja2VyIENvbXBvc2UKCmBgYGJhc2gKZ2l0IGNsb25lIGh0dHBzOi8vZ2l0ZWEuaGlkZWF3YXlnYW1pbmcuY29tLmF1L2plc3Npa2l0dHkvZnJhbWJlLmdpdApjZCBmcmFtYmUKYGBgCgpFZGl0IGBkb2NrZXItY29tcG9zZS55bWxgIGFuZCBzZXQgeW91ciBgSU1NSUNIX1VSTGAgYW5kIGBJTU1JQ0hfQVBJX0tFWWAsIHRoZW46CgpgYGBiYXNoCmRvY2tlciBjb21wb3NlIHVwIC1kCmBgYAoKT3BlbiBgaHR0cDovL3lvdXItc2VydmVyOjMwMzBgIGluIGEgYnJvd3NlciBvbiB5b3VyIHRhYmxldC9zY3JlZW4uCgojIyMgMy4gUnVuIHdpdGggRG9ja2VyIGRpcmVjdGx5CgpgYGBiYXNoCmRvY2tlciBidWlsZCAtdCBmcmFtYmUgLgpkb2NrZXIgcnVuIC1kIFwKICAtLW5hbWUgZnJhbWJlIFwKICAtcCAzMDMwOjMwMDAgXAogIC1lIElNTUlDSF9VUkw9aHR0cDovL3lvdXItaW1taWNoLXNlcnZlcjoyMjgzIFwKICAtZSBJTU1JQ0hfQVBJX0tFWT15b3VyLWFwaS1rZXkgXAogIC0tcmVzdGFydCB1bmxlc3Mtc3RvcHBlZCBcCiAgZnJhbWJlCmBgYAoKIyMg8J+UkSBBdXRoZW50aWNhdGlvbgoKIyMjIEFkbWluIERhc2hib2FyZCBMb2dpbgoKUHJvdGVjdCB0aGUgYWRtaW4gZGFzaGJvYXJkIHdpdGggYSB1c2VybmFtZSBhbmQgcGFzc3dvcmQ6CgpgYGB5YW1sCmVudmlyb25tZW50OgogIC0gQURNSU5fVVNFUk5BTUU9YWRtaW4KICAtIEFETUlOX1BBU1NXT1JEPXlvdXItc2VjdXJlLXBhc3N3b3JkCmBgYAoKV2hlbiBgQURNSU5fUEFTU1dPUkRgIGlzIHNldCwgYWNjZXNzaW5nIGAvYWRtaW5gIHJlcXVpcmVzIHNpZ25pbmcgaW4uIFdoZW4gbm90IHNldCwgdGhlIGRhc2hib2FyZCBpcyBvcGVuICh1c2VmdWwgZm9yIHRydXN0ZWQgbG9jYWwgbmV0d29ya3MpLgoKIyMjIEFQSSBUb2tlbiBmb3IgRXh0ZXJuYWwgQWNjZXNzCgpFbmFibGUgdG9rZW4tYXV0aGVudGljYXRlZCBSRVNUIEFQSSBhY2Nlc3MgZm9yIEhvbWUgQXNzaXN0YW50LCBzY3JpcHRzLCBvciBvdGhlciBleHRlcm5hbCB0b29sczoKCmBgYHlhbWwKZW52aXJvbm1lbnQ6CiAgLSBGUkFNQkVfQVBJX1RPS0VOPXlvdXItc2VjcmV0LXRva2VuLWhlcmUKYGBgCgojIyDwn5SMIFJFU1QgQVBJCgpXaGVuIGBGUkFNQkVfQVBJX1RPS0VOYCBpcyBjb25maWd1cmVkLCB0aGUgZm9sbG93aW5nIGVuZHBvaW50cyBhcmUgYXZhaWxhYmxlOgoKIyMjIExpc3QgQ29ubmVjdGVkIEZyYW1lcwoKYGBgCkdFVCAvYXBpL2NsaWVudHMKQXV0aG9yaXphdGlvbjogQmVhcmVyIHlvdXItc2VjcmV0LXRva2VuLWhlcmUKYGBgCgpSZXR1cm5zIGFsbCBjb25uZWN0ZWQgZnJhbWUgY2xpZW50cyB3aXRoIHRoZWlyIHN0YXR1cywgSVAsIG5hbWUsIGFuZCBjb25maWcuCgojIyMgU2VuZCBDb21tYW5kIHRvIGEgRnJhbWUKCmBgYApQT1NUIC9hcGkvY2xpZW50cy86aWQvY29tbWFuZApBdXRob3JpemF0aW9uOiBCZWFyZXIgeW91ci1zZWNyZXQtdG9rZW4taGVyZQpDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb24KCnsKICAiYWN0aW9uIjogIm5leHQiLAogICJwYXlsb2FkIjoge30KfQpgYGAKCkF2YWlsYWJsZSBhY3Rpb25zOiBgc3RhcnRgLCBgc3RvcGAsIGBuZXh0YCwgYHByZXZgLCBgc2xlZXBLine truncated # Frambe
<p align="center">
<img src="public/img/icon.png" alt="Frambe" width="180">
</p>
A lightweight, self-contained Docker web application that connects to your [Immich](https://immich.app/) server and displays photos in a beautiful full-screen slideshow — perfect for turning old tablets, spare screens, and Raspberry Pis into digital photo frames.
## ✨ Features
- **Immich API Integration** — Connects securely via API key (kept server-side)
- **Album Browser** — Select any album, random photos, or favorites only
- **Person / Face Support** — Display photos of a specific person via Immich's face recognition
- **Admin Dashboard** — Real-time WebSocket-based control panel for all connected frames
- **Admin Authentication** — Optional username/password login to protect the admin dashboard
- **REST API with Token Auth** — Control frames from Home Assistant, scripts, or external tools
- **URL-Based Zero-Touch Launch** — Skip the setup screen entirely with query parameters
- **Auto-Refresh** — Periodically checks for new photos added to the source album/person
- **Smooth Crossfade** — Double-buffered image transitions with configurable duration
- **Background Blur** — Blurred backdrop fills the space behind non-covering images
- **Clock & Date Overlay** — Always know the time at a glance
- **EXIF Info** — Shows photo location, date, and camera info
- **Progress Bar** — Subtle indicator of time until next photo
- **Touch Controls** — Tap left/right edges to navigate, centre to toggle overlay
- **Keyboard Controls** — Arrow keys, Space, F (fullscreen), I (info), Esc (exit)
- **Screen Wake Lock** — Prevents screen sleep on supported devices
- **Responsive** — Works on any screen size from phone to TV
- **Older Device Friendly** — Vanilla HTML/CSS/JS, no heavy frameworks
- **Docker Containerised** — Single container, minimal footprint
## 🚀 Quick Start
### 1. Get your Immich API Key
1. Open your Immich web interface
2. Click your profile picture → **Account Settings** → **API Keys**
3. Create a new key with `asset.read` and `album.read` permissions
### 2. Run with Docker Compose
```bash
git clone https://gitea.hideawaygaming.com.au/jessikitty/frambe.git
cd frambe
```
Edit `docker-compose.yml` and set your `IMMICH_URL` and `IMMICH_API_KEY`, then:
```bash
docker compose up -d
```
Open `http://your-server:3030` in a browser on your tablet/screen.
### 3. Run with Docker directly
```bash
docker build -t frambe .
docker run -d \
--name frambe \
-p 3030:3000 \
-e IMMICH_URL=http://your-immich-server:2283 \
-e IMMICH_API_KEY=your-api-key \
--restart unless-stopped \
frambe
```
## 🔑 Authentication
### Admin Dashboard Login
Protect the admin dashboard with a username and password:
```yaml
environment:
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=your-secure-password
```
When `ADMIN_PASSWORD` is set, accessing `/admin` requires signing in. When not set, the dashboard is open (useful for trusted local networks).
### API Token for External Access
Enable token-authenticated REST API access for Home Assistant, scripts, or other external tools:
```yaml
environment:
- FRAMBE_API_TOKEN=your-secret-token-here
```
## 🔌 REST API
When `FRAMBE_API_TOKEN` is configured, the following endpoints are available:
### List Connected Frames
```
GET /api/clients
Authorization: Bearer your-secret-token-here
```
Returns all connected frame clients with their status, IP, name, and config.
### Send Command to a Frame
```
POST /api/clients/:id/command
Authorization: Bearer your-secret-token-here
Content-Type: application/json
{
"action": "next",
"payload": {}
}
```
Available actions: `start`, `stop`, `next`, `prev`, `sleep`, `wake`, `refresh`, `setSource`, `setConfig`
### Home Assistant Example
```yaml
rest_command:
frambe_next_photo:
url: "http://frambe-server:3030/api/clients/{{ client_id }}/command"
method: POST
headers:
Authorization: "Bearer your-secret-token-here"
Content-Type: "application/json"
payload: '{"action": "next"}'
```
Authentication can also be provided via `x-api-token` header or `?token=` query parameter.
## 🔗 Zero-Touch URL Parameters
Skip the setup screen entirely by passing query parameters. This is ideal for dedicated frames — just bookmark the URL on each tablet:
| URL | What it shows |
|---|---|
| `http://server:3030/?album=ALBUM_UUID` | Photos from a specific album |
| `http://server:3030/?person=PERSON_UUID` | Photos of a specific person (face recognition) |
| `http://server:3030/?favorites` | Favorite photos only |
| `http://server:3030/?random` | Random photos from the library |
You can find album and person UUIDs in Immich's web interface URL bar when viewing an album or person.
## ⚙️ Configuration
All settings are via environment variables:
| Variable | Default | Description |
|---|---|---|
| `IMMICH_URL` | *(required)* | Your Immich server URL |
| `IMMICH_API_KEY` | *(required)* | Immich API key |
| `SLIDESHOW_INTERVAL` | `30` | Seconds between photos |
| `TRANSITION_DURATION` | `2` | Crossfade duration in seconds |
| `IMAGE_FIT` | `contain` | `contain` or `cover` |
| `SHUFFLE` | `true` | Randomise photo order |
| `BACKGROUND_BLUR` | `true` | Show blurred backdrop |
| `SHOW_CLOCK` | `true` | Display clock overlay |
| `SHOW_DATE` | `true` | Display date overlay |
| `SHOW_EXIF` | `true` | Display photo metadata |
| `SHOW_PROGRESS` | `true` | Display progress bar |
| `REFRESH_INTERVAL` | `300` | Seconds between source refresh checks (new photos) |
| `ALBUM_ID` | *(empty)* | Auto-start with specific album (env-based) |
| `SHOW_FAVORITES_ONLY` | `false` | Auto-start with favorites (env-based) |
| `ADMIN_USERNAME` | `admin` | Admin dashboard login username |
| `ADMIN_PASSWORD` | *(empty)* | Admin dashboard password (leave empty to disable auth) |
| `FRAMBE_API_TOKEN` | *(empty)* | API token for REST endpoint access (leave empty for open access) |
| `PORT` | `3000` | Internal server port (Docker maps externally via compose) |
## 🎮 Controls
### Touch / Mouse
- **Left 20%** of screen — Previous photo
- **Centre 60%** — Toggle overlay (clock, info, close button)
- **Right 20%** — Next photo
### Keyboard
- `←` / `→` — Previous / Next photo
- `Space` — Next photo
- `F` — Toggle fullscreen
- `I` — Toggle info overlay
- `Esc` — Exit to album selection
## 📱 Tablet Setup Tips
1. Open the frame URL in your tablet's browser (use a `?album=` or `?person=` URL for zero-touch)
2. Add to Home Screen for a full-screen app experience
3. Enable kiosk mode or guided access to lock to the app
4. Disable screen timeout in your device settings
## 📋 Version History
- **1.4.0** — Admin login (username/password), API token auth for external access (Home Assistant), REST endpoints (`GET /api/clients`, `POST /api/clients/:id/command`)
- **1.3.0** — Admin dashboard with real-time WebSocket frame management, video support, person/face support
- **1.2.1** — Fix port mapping (3030:3000 external:internal), fix URL param auto-launch not starting slideshow
- **1.2.0** — URL params (`?album=`, `?person=`, `?favorites`, `?random`), person/face support, periodic auto-refresh, app icon, default port changed to 3030
- **1.1.0** — Rebrand to Frambe
- **1.0.0** — Initial release: album browser, slideshow with crossfade, clock/date/EXIF overlays, touch & keyboard controls, Docker deployment
## 📄 License
MIT