Turn a Google Photos shared album, an Immich or PhotoPrism library, an iCloud Shared Album, a Synology Photos library, a Nextcloud folder, a local/NAS folder, or any Home Assistant Media Source into a fully controllable Home Assistant camera slideshow.
Clean. Flexible. Fully runtime configurable. Designed for dashboards.
Album Slideshow creates a camera entity that automatically cycles through images from:
- Google Photos shared albums
- Immich (direct API): album, person, favorites, all, random, or a custom search
- PhotoPrism (direct API): album, person, favorites, all, or a custom search
- iCloud Shared Albums (public link)
- Synology Photos (direct API): favorites, albums, people, places, tags or subjects
- Nextcloud (WebDAV folder): any folder in your files, with full metadata
- Local folders and NAS mounted directories
- Home Assistant Media Source (local media, Jellyfin, ...)
All behavior is exposed as Home Assistant entities. Adjust everything live without YAML edits or restarts.
- Auto advancing camera entity
- Configurable slide interval
- Manual next slide button
- Album refresh control
- Google Photos shared albums
- Immich (direct API): album, person, favorites, all, random, or a custom search, with full metadata
- PhotoPrism (direct API): album, person, favorites, all, or a custom search, with full metadata
- iCloud Shared Albums (public link), with capture date + captions
- Synology Photos (direct API): favorites, albums, people, places, tags or subjects, with full metadata
- Nextcloud (WebDAV folder): any folder in your files (app-password auth, recursive), with full metadata
- Local folder paths and NAS mounted directories
- Home Assistant Media Source (local media, Jellyfin, ...)
- Optional recursive scanning
- Reads capture date so date-filter modes work (EXIF
DateTimeOriginalwithOffsetTimeOriginalfor local files; Immich's own capture date for the Immich provider) - Surfaces GPS as
latitude/longitudecamera attributes - Human-readable
locationlabel (reverse-geocoded via OpenStreetMap Nominatim for local files, or Immich's own place data); per-album opt-out for geocoding in the integration's Configure dialog
- Date filter: last 7 / 30 / 365 days, this month, this year, On this day memories
- Order modes: random, album order, newest taken, oldest taken, newest added, oldest added
- Capture date and upload date exposed as camera attributes (with paired-photo support)
- Pause switch holds the current slide indefinitely
- Manual "Next slide" button still works while paused
- Survives Home Assistant restarts
- Smooth slide transitions rendered in the browser, so they stay buttery even on lower-end hardware
- Effects:
random,none,fade,slide-left,slide-right,slide-up,slide-down,wipe-left,wipe-right,zoom randompicks a different effect per slide (and avoids repeating the previous one)- Configurable duration and CSS easing
- Aspect ratio + fill mode inheritance from the camera entity (cover / contain / blur backdrop)
| Mode | Behavior |
|---|---|
| Pair | Display two mismatched images side by side |
| Single | Render single image using selected fill mode |
| Avoid | Skip mismatched images |
| Mode | Behavior |
|---|---|
| Blur | Image over blurred background |
| Cover | Crop to fill canvas |
| Contain | Fit inside canvas with bars |
- Configurable aspect ratio such as 16:9, 4:3, 1:1, 9:16
- Shuffle or album order
- Pair divider size/color control
The following entities allow you to adjust slideshow behavior without restarting Home Assistant.
| Entity Type | Name | Default | Accepted Values | Description |
|---|---|---|---|---|
| Number | Slide interval | 60 | Any positive integer (seconds) | Time between slides |
| Number | Album refresh | 24 | Any positive integer (hours) | How often album contents refresh |
| Number | Pair divider size | 8 | 0-64 (px) | Width of divider between paired images |
| Number | Image cache size | 75 | 50-1000 (MB) | Memory budget for downloaded image data (per album) |
| Select | Fill mode | blur | blur, cover, contain | How images fill the canvas |
| Select | Orientation mismatch | pair | pair, single, avoid | Handling of portrait and landscape mismatch |
| Select | Order mode | random | random, album_order, newest_taken, oldest_taken, newest_added, oldest_added | Slide ordering behavior |
| Select | Aspect ratio | 16:9 | 16:9, 4:3, 1:1, 9:16, and more | Canvas aspect ratio |
| Select | Max resolution | 4K (2160p) | 480p, 720p, 1080p, 1440p, 4K (2160p), original | Cap output resolution by short edge; use original to render at native size |
| Select | Date filter | off | off, last_7_days, last_30_days, last_365_days, this_month, this_year, on_this_day | Restrict the slideshow to a date window based on photo capture date |
| Text | Pair divider color | #FFFFFF | Hex, named colors, transparent | Divider color between paired images |
| Switch | Pause slideshow | off | on / off | Hold the current frame; advances pause until turned off |
Album Slideshow Camera is available in HACS.
- Download the latest release
- Copy
custom_components/album_slideshow
into
config/custom_components/
- Restart Home Assistant
- Add the integration from Devices & services
Pick the provider that matches where your photos live:
| Provider | Best for | Date filter / ordering | Location | Description caption |
|---|---|---|---|---|
| Google Photos | A shared album link | ✅ (dates only) | ❌ | ❌ |
| Immich | An Immich server (album, person, favorites, all, search) | ✅ | ✅ | ✅ |
| PhotoPrism | A PhotoPrism server (album, person, favorites, all, search) | ✅ | ✅ | ✅ |
| iCloud | An iCloud Shared Album public link | ✅ | ❌ | ✅ |
| Synology | A Synology Photos library (favorites, albums, people, places, tags, subjects) | ✅ | ✅ | ✅ |
| Nextcloud | Any folder in your Nextcloud files (WebDAV, app password) | ✅ | ✅ | ✅ |
| Local Folder | Files on the HA host / NAS | ✅ | ✅ | ✅ |
| Media Source | Any HA media source with no API (local media, Jellyfin, ...) | ❌ | ❌ | ❌ |
Media Source and Google Photos serve photos as URLs, so there is no EXIF to read. For full metadata (dates, location, description), use Local Folder for local/NAS files or the Immich / PhotoPrism provider for a self-hosted photo server. The Media Source route also works with those but without metadata, so prefer the direct provider when you have one.
- Open a shared Google Photos album
- Copy the shared link such as
https://photos.app.goo.gl/... - Add the integration
- Paste the link
The Immich provider connects straight to your Immich server for full photo metadata: capture date, GPS/location, and description all work, and you can slideshow far more than just an album. If you have an Immich server, prefer this over the Media Source route.
- In Immich, create an API key: Account Settings → API Keys → New API Key.
Read scopes are enough:
asset.read,asset.view,asset.download,album.read,person.read. - Add the integration and choose Immich (direct API, full metadata).
- Enter your Immich URL (e.g.
http://192.168.1.10:2283) and the API key. - Give it a name, tick what you want to show, and choose the image quality.
Tick any mix of these and they are combined into one slideshow:
| Option | What it adds |
|---|---|
| Albums | Photos from the albums you pick (searchable, with Select all) |
| People | Photos of the people you pick (searchable, with Select all) |
| Include favorites | Everything you have favorited in Immich |
Immich has no "OR" search, so the integration queries each album and each person separately and merges the results, deduplicated. That means People gives you every photo that includes any of them (not only the group shots where they all appear together), and you can freely mix albums, people and favorites - for example "the Family album OR these 5 people OR my favorites". Leave everything empty to show your whole library (all photos).
Advanced: you can also add an Immich search filter (JSON) to fold its results
into the same slideshow. It is passed to
Immich's search/metadata
endpoint (with type forced to images). Examples:
{ "city": "Paris", "isFavorite": true }{ "country": "Japan", "takenAfter": "2023-01-01T00:00:00Z" }- Preview (default) - a downscaled preview; smoothest slideshow.
- Full size - the large rendered version.
- Original - the untouched original file (largest, slowest).
- The API key is sent only as a server-side request header, so it never
appears in the camera's
current_urlattribute or reaches the browser. Home Assistant fetches and re-serves the images; your Immich server is never exposed to the dashboard client. - Capture dates come from the asset list up front, so date filters and date ordering work immediately. Location and description are filled in by a background pass (one lightweight call per photo, cached), so they appear shortly after the first load, the same way local-folder EXIF does.
The PhotoPrism provider connects straight to your PhotoPrism server for full photo metadata: capture date, GPS/location, and description all work, and you can combine albums, people and favorites into one slideshow. If you have a PhotoPrism server, prefer this over the Media Source route.
- Add the integration and choose PhotoPrism (direct API, full metadata).
- Enter your PhotoPrism URL (e.g.
http://192.168.1.10:2342). - Choose how to authenticate:
- App password (recommended) - in PhotoPrism go to Settings → Account → Apps and Devices and create one, then paste it here.
- Username + password - your normal PhotoPrism login. The password is stored so the integration can refresh its session automatically; it is kept on the server side and never reaches the browser.
- Give it a name, tick what you want to show, and choose the image quality.
Works exactly like the Immich picker - tick any mix and they are combined into one slideshow:
| Option | What it adds |
|---|---|
| Albums | Photos from the albums you pick (searchable, with Select all) |
| People | Photos of the people you pick (searchable, with Select all) |
| Include favorites | Everything you have favorited in PhotoPrism |
PhotoPrism has no "OR" across filters, so the integration queries each album and each person separately and merges the results, deduplicated - so People gives you every photo that includes any of them, and you can freely mix albums, people and favorites. Leave everything empty to show your whole library.
Advanced: you can also add a PhotoPrism search query to fold its results into the same slideshow, for example:
color:red
country:jp year:2023
- Preview (default, 1280px) - smoothest slideshow.
- Full size (1920px) - more detail.
- High detail (2560px) - largest, slowest.
- PhotoPrism serves thumbnails with a rotatable preview token in the URL (its own cookie-free scheme), so no login token is ever placed in the image URL.
- All photo metadata (date, location, description) comes back inline with the photo list, so date filters, location and captions work from the first load with no background pass.
The iCloud provider slideshows a public iCloud Shared Album. No Apple ID or password is needed - the album's share link is the only credential, the same way anyone with the link can view it on the web.
- In the Photos app (iPhone/iPad/Mac), open the shared album, tap the
people/share icon, and enable Public Website (then copy that link). The
link looks like
https://www.icloud.com/sharedalbum/#B2Xabc.... - Add the integration, choose iCloud Shared Album, paste the link, give it a name, and pick an image quality.
- Full size (default) - the largest version Apple generated (usually around 2048px); best for a slideshow.
- Preview - a small thumbnail; fastest / least bandwidth.
- Capture date and captions work (both come inline with the album data), so date filters, date ordering, and the caption overlay all apply.
- No location. Apple strips GPS from shared-album web data, so the
latitude/longitude/locationattributes stay empty (same as Google Photos). - Contributors can keep adding photos to the album; new ones show up on the next refresh.
- The image URLs Apple hands out are signed and expire after about a day, so the integration re-fetches them on every album refresh.
The Synology provider connects straight to the Photos package on your Synology NAS for full photo metadata (capture date, GPS location and captions). Like the Immich and PhotoPrism providers, you can combine any mix of favorites, albums (including albums shared with you), people, places, tags and subjects into one slideshow, from either the personal ("My Photos") or shared ("Shared Space") library.
- Add the integration and choose Synology Photos (direct API, full metadata).
- Enter your DSM address (e.g.
http://192.168.1.10:5000, or your HTTPS / QuickConnect URL) and an account username and password. - Choose the Personal or Shared library.
- If the account has two-factor authentication, also enter a current 6-digit code. This is only needed once - a trusted-device token is stored so later refreshes never prompt for a code again.
- Tick what you want to show (favorites, albums, people, places, tags, subjects) - or leave everything unticked for all photos - then name it and choose an image quality.
Combining sources. Synology has no "OR" across categories, so the integration queries each ticked album/person/place/tag/subject separately and merges the results (duplicates removed). Favorites and subjects are a Personal library feature.
Synology serves pre-generated thumbnails:
- Large (default) - the biggest thumbnail; best for a slideshow.
- Medium - a good balance of detail and bandwidth.
- Small - a small thumbnail; fastest / least bandwidth.
- Date, location and captions all work - Synology returns capture date, GPS coordinates and a reverse-geocoded place name inline, so date filters, date ordering, the location attribute, and the caption overlay all apply.
- The password is stored so the integration can re-authenticate when its session expires. The session id is sent only server-side (it never appears in the camera's image URL or the browser).
- New photos added to the album or library show up on the next refresh.
- Albums that another user shared with your account appear under Albums tagged "(shared)"; they are fetched by their share passphrase.
Use a dedicated account. Create a normal (non-admin) DSM user, give it access only to the Photos content you want to show, and use that here rather than your admin login.
The Nextcloud provider slideshows any folder in your Nextcloud files over WebDAV, with full photo metadata (capture date, GPS location and captions). It works on any Nextcloud server - no Photos or Memories app is required.
- In Nextcloud, create an app password: Settings -> Security -> Devices & sessions -> Create new app password. Copy the generated password (it is shown only once).
- Add the integration and choose Nextcloud (WebDAV folder, full metadata).
- Enter your server URL (e.g.
https://cloud.example.com), your username, and the app password. - Point it at a folder path (e.g.
Photos/Family), or leave it blank for your whole files root. Tick Include subfolders to recurse. - Name it and pick an image quality.
- Preview (default) - a resized thumbnail from Nextcloud's
core/previewendpoint; smoothest slideshow. - Original - the untouched original file straight off WebDAV (largest, slowest).
- Date, location and captions all work. Nextcloud has no metadata-only API for a folder, so the integration reads EXIF the same way the Local Folder provider does: it downloads each original photo once in the background and reads its EXIF/IPTC/XMP. Progress is tracked by the same Enrichment progress diagnostic sensor, and the same reverse-geocoding opt-out applies in the integration's Configure dialog.
- The app password is stored so the integration can re-list the folder on each refresh. It is sent to Nextcloud server-side only (HTTP Basic auth) and never appears in the camera's image URL or the browser.
- New photos dropped into the folder show up on the next refresh.
- Videos and non-image files are skipped.
Use any folder accessible to Home Assistant.
Helpful path mappings:
| Input | Resolves To |
|---|---|
/local/... |
/config/www/... |
media/... |
/media/... |
media/local/... |
/media/... |
For NAS:
- Mount it first
- Use the mounted path
For local-folder entries the integration reads EXIF metadata in the background after every refresh:
- Capture date —
DateTimeOriginalis preferred; if missing, the file's modification time is used so date-based ordering still works for screenshots and scans. WhenOffsetTimeOriginalis present (most modern cameras and phones) it is honoured; otherwise the timestamp is interpreted as the host's local time. - GPS coordinates —
GPSLatitude/GPSLongitudeare exposed as thelatitude/longitudecamera attributes.(0, 0)"null island" stamps are ignored. - Reverse-geocoded location — by default the integration calls the
public Nominatim (OpenStreetMap)
service to translate coordinates into a human-readable label such as
"Lisbon, Portugal", exposed as thelocationattribute. Coordinates are rounded to ~100 m before lookup and the answer is cached on disk, so the same neighbourhood is only ever fetched once. Nominatim's free-tier policy (1 req/sec, identifying User-Agent) is respected.
Privacy / opt-out: if you'd rather not send any coordinates to
OpenStreetMap, open Settings → Devices & Services → Album Slideshow → your
album → Configure and turn off Reverse-geocode EXIF GPS coordinates.
The latitude/longitude attributes still work; only the location
label is suppressed. The opt-out is per-album.
Progress for both phases is exposed as the Enrichment progress
diagnostic sensor (percent complete, with phase, exif_done,
geocode_done etc. as attributes).
The Media Source provider points the slideshow at any Home Assistant Media Source folder. This is the easiest way to slideshow an Immich album or a recognized person, and it also works with local media, Jellyfin, and any other integration that exposes a media source.
- Add the integration and choose Media Source (Immich, local media, ...).
- Give the album a name.
- Paste the Media Source id of the folder you want (it starts with
media-source://). See below for how to find it.
The integration walks that folder (and its subfolders) collecting images,
skipping videos, system folders (e.g. Synology @eaDir), and non-web
formats (.psd, .tiff, .heic, RAW). It re-reads the folder on every
album refresh, so photos you add later show up automatically.
Immich
- Open the sidebar Media browser (or a Media card).
- Browse into Immich → Albums / People / Tags → your album.
- The folder's id looks like
media-source://immich/<config-entry-id>|albums|<album-id>(people and tags use|people|/|tags|). To copy the exact value, open your browser's developer tools → Network tab, filter formedia_source, click into the folder, and read the folder'smedia_content_idfrom themedia_source/browse_mediaresponse.
Local media (e.g. a NAS folder under /media)
You can build the id from the path. Take whatever comes after /media/ and
prefix it with media-source://media_source/local/:
| Media path | Media Source id |
|---|---|
/media/local/Pictures/Family |
media-source://media_source/local/Pictures/Family |
/media/Photos/2024 |
media-source://media_source/local/Photos/2024 |
Point the id at a folder, not a single file. Don't URL-encode spaces in the config field, type them normally.
Media Source hands the slideshow URLs, not files, so there is no EXIF to read. For Media Source albums this means:
- no date filter / date ordering (no capture or upload date)
- no GPS
latitude/longitude/location - no description caption
This is the same limitation as the Google Photos provider. If your photos
are local files (for example a NAS folder mounted under /media), use the
Local Folder provider instead of Media Source to get full EXIF-based
dates, location, and description captions.
Each album you configure creates the following entities in Home Assistant.
| Entity | Description |
|---|---|
| Slideshow camera | The live slideshow feed rendered according to your current settings |
| Entity | Description |
|---|---|
| Next slide | Immediately advances to the next image |
| Refresh album | Re-fetches album contents |
| Entity | Source | Description |
|---|---|---|
| Album title | All | Title of the source album |
| Media count | All | Number of images currently available |
| Image cache usage (diagnostic) | All | Current download cache size in MB |
| Enrichment progress (diagnostic) | Local folder / Immich | Percent of items whose metadata has been read (EXIF/GPS for local folder, per-asset detail for Immich; and, when enabled, reverse-geocoded). Attributes include phase, exif_done/exif_total, geocode_done/geocode_total. |
The slideshow camera exposes per-frame metadata as attributes (use with state_attr('camera.x', '<name>') in templates):
| Attribute | Type | Description |
|---|---|---|
album_title |
string | Title of the source album |
media_count |
int | Photos in the active playlist (after date filter) |
media_count_total |
int | Total photos available before filtering |
current_index |
int | Index of the current slide |
current_filename |
string | null | Source filename when known |
current_url |
string | null | URL of the current slide |
current_is_portrait |
bool | null | Orientation of the current slide |
captured_at |
string | list | null | ISO-8601 capture date. List of [primary, partner] when paired (top/left first). For local files this is read from EXIF (or the file's mtime as a fallback). |
captured_at_primary |
string | null | Capture date of the primary image only |
uploaded_at |
string | null | ISO-8601 date when added to the album (Google Photos only) |
byte_size |
int | null | Original file size in bytes (Google Photos only) |
latitude |
float | null | GPS latitude in decimal degrees (local folder + Immich) |
longitude |
float | null | GPS longitude in decimal degrees (local folder + Immich) |
location |
string | null | Reverse-geocoded label (e.g. "Lisbon, Portugal"). Empty when reverse-geocoding is disabled or has not yet completed for this file. |
description |
string | null | Free-text photo caption. From EXIF ImageDescription / IPTC Caption-Abstract / XMP dc:description (local folder), or the Immich photo description (Immich provider). |
caption_frames |
list | Structured per-image caption metadata: one entry for a normal slide, two (top/left first) for a pair. Each entry has captured_at, location, latitude, longitude, description. Used by the card's caption overlay. |
pair_orientation |
string | null | How a paired slide is split: horizontal (left/right) or vertical (top/bottom). null for single slides. |
paused |
bool | Whether the slideshow is paused |
date_filter |
string | Active date filter mode |
frame_id |
int | Monotonic counter incremented on every committed slide. Used by the card to detect new frames |
The integration ships with a custom Lovelace card that does the slide-to-slide transition entirely in the browser. The server only renders one still per slide change; the card cross-fades in CSS, which the browser composites on the GPU. Result: a smooth dissolve on a Pi 4, even with several albums on screen.
The card is registered automatically when the integration loads; you do not need to add it as a HACS frontend repository or configure a Lovelace resource manually. After installing or upgrading, hard-refresh the dashboard once (Ctrl+Shift+R) so the browser picks up the script.
A visual editor is available - pick Album Slideshow from the card picker in Lovelace and the form will appear automatically.
type: custom:album-slideshow-card
entity: camera.album_slideshow_living_roomtype: custom:album-slideshow-card
entity: camera.album_slideshow_living_room
transition: random # random | none | fade | slide-left
# | slide-right | slide-up | slide-down
# | wipe-left | wipe-right | zoom
duration: 800 # ms; CSS transition length
easing: ease-in-out # any CSS timing function (ease, linear, cubic-bezier(...))
aspect_ratio: 16/9 # CSS aspect-ratio value (16/9, 4/3, 1/1, auto)
fit: auto # auto | cover | contain
# auto inherits the camera's fill_mode (cover / contain / blur)
background: '#000' # color shown behind contained images
tap_action: none # none | more-info
caption: # overlay the photo's date, location and/or description
show: [date, location] # any of: date, location, description (order = display order)
position: bottom-left # top/center/bottom + -left/-center/-right, or center
date_format: medium # medium | full | month_year | year | numeric
# | weekday | relative, or a custom token string
# (YYYY, MMMM, MMM, MM, M, DD, D, dddd, ddd)
per_image: true # caption each half of a portrait pair separately
color: '#ffffff' # any CSS color
font_size: 14px # any CSS size
font_weight: medium # light | normal | medium | semibold | bold
shadow: true # drop shadow for readability on bright photostransition: randompicks a different effect per slide and avoids repeating the previous one.fit: autoreads the camera'sfill_modeattribute.blurrenders the slide ascontainplus a blurred backdrop layer behind it.- Caption overlay: omit the
caption:block (or setshow: []) to disable it. The date comes fromcaptured_at;locationanddescriptioncome from photo metadata. Location and description are available with the Local Folder and Immich providers (they are simply skipped when a photo has none); Google Photos and Media Source slides show only the date. On a portrait pair,per_image: trueanchors each photo's own date/location/description to its half; set it tofalsefor a single caption over the whole frame. date_formataccepts a preset name or a custom token string. Presets are locale-aware (they follow your Home Assistant language). Example custom format:'D MMMM YYYY'->29 July 2023.- Every slide commit increments the camera's
frame_idattribute. The card cache-busts the camera proxy URL with that value, so the browser refetches a fresh JPEG on every change instead of serving a stale cached image. - If the entity is unavailable, the card shows a "Camera not ready" placeholder.
To remove visible spacing between paired images:
- Set Pair divider color to
transparent - Keep divider size greater than
0
Also accepted values:
noneclearrgba(0,0,0,0)transperantcommon misspelling
When transparency is used, the integration outputs PNG to preserve alpha.
- Public shared albums only (link sharing must be enabled)
- Up to 20,000 photos per album
- Videos are skipped
- Internet connection required
- Relies on Google's public web endpoints; if Google changes them, the integration falls back to a 300-photo limit until the scraper is updated
- The last successful album fetch is cached to disk; if a refresh fails or returns no photos, the slideshow keeps running with the cached list
- Requires an Immich server reachable from Home Assistant and an API key
- Videos are skipped
- Home Assistant fetches and re-serves images, so the Immich server does not need to be reachable from the dashboard client (and the API key never leaves the server)
- Location and description are read per photo in the background, so they appear shortly after the first load
- Images only
- No video support
If you enjoy this card and want to support its development: