5.3 KiB
Photo sources
Photo sources are independent read-only providers. They never call a frame driver. SQLite persists source definitions and Scheduler jobs; passwords are not stored there. The shared DisplayService handles fitting, upload, idempotency, overrides and restore.
NAS local folder
Add the actual existing photo directory to .env:
NAS_PHOTOS_DIR=/volume2/photo
The path above is an example, not a detected directory. Enable the optional mount:
docker compose -f docker-compose.yml -f deploy/docker-compose.photos.yml config -q
docker compose -f docker-compose.yml -f deploy/docker-compose.photos.yml up -d
The folder is mounted read-only at /photos. The existing container user must
already have read/traverse permission. Frame Flow does not change NAS permissions.
Missing host folders fail explicitly rather than being created automatically.
Open Gallery → Photo sources → Add source, choose NAS local folder,
enter a relative folder (. for root or family for a subfolder).
Supported formats: JPEG, PNG, WebP. Optional recursion excludes hidden directories,
Synology @eaDir thumbnail trees, and symlinks. Original files remain unchanged.
WebDAV
Open Settings and allow the server hostname under Image URL hosts.
Add a WebDAV source using a plain HTTPS directory URL on port 443.
The implementation uses read-only PROPFIND Depth: 1 and GET, following
RFC 4918.
This version lists images immediately inside one folder; recursive WebDAV traversal
is not supported. Basic authentication is supported; OAuth, SSO and Digest are not.
Redirects, private-address endpoints and URL-embedded credentials are rejected.
For authentication, reference an environment variable such as
FRAME_FLOW_SOURCE_CLOUD; set its value to a JSON object containing username
and password, or set FRAME_FLOW_SOURCE_CLOUD_FILE to a mounted Secret file.
Compose's env_file supplies the variable; a Secret file belongs in the existing
/config mount with restricted permissions and container read access. Never commit
credentials. The UI/API stores only the variable name.
Use
- Browse photos returns paginated metadata (50 items/page), without fetching originals.
- Preview random photo imports one selected photo into local Frame Flow storage; the frame remains unchanged. Display uses that exact previewed asset.
- Schedule random photos creates a device-bound Cron job, paused by default. Each execution picks a random photo; ordinary random selection can repeat. Editing the job supports other schedule types, fitting/profile via advanced JSON, and the existing temporary override/restore options.
- Sources can be edited, disabled or removed. Remove referencing jobs before deletion.
Metadata is cached for 60 seconds, with explicit refresh. Each catalog is limited to 10,000 supported images (not a complete inventory for larger folders). Maximum selected image size is 20 MiB; WebDAV XML responses are limited to 2 MiB. Preview imports use the existing local asset store; monitor disk space over time. Unreadable/invalid images fail the operation without retrying frame writes.
API
GET /api/v1/photo-sourcesPUT /api/v1/photo-sources/{id}(admin)DELETE /api/v1/photo-sources/{id}(admin)GET /api/v1/photo-sources/{id}/images?offset=0&limit=50&refresh=false
Display or Scheduler content:
{"type":"photo_source","source_id":"family","fit":"contain","profile":"color"}
Optional item_id selects an exact catalog item. Omit it for random selection.
The device upload endpoint accepts the same content with display_now=false
(default) to import/preview locally. POST /api/v1/display performs the usual
protected asynchronous device display. Schemas are in /openapi.json and /docs.
Native Aliyun Drive/Baidu Drive/Google Drive adapters are not implemented. A compatible WebDAV gateway or an independently managed NAS sync folder can be used. Frame Flow does not install a gateway or receive vendor API credentials automatically.
Date-folder captions / 整理照片文字
Enable Only photos in date-prefixed folders and Show folder caption below
the photo when editing a source. Curated sources created by the UI increase the
catalog limit to 100,000 photos; other sources default to 10,000. The API exposes
catalog_limit explicitly. It remains a bounded catalog; reaching the limit is
shown in the UI.
Example folder name: 20261005 家庭出游@示例地点.
The image contains the photo and three separate caption lines:
家庭出游
2026-10-05
示例地点
Without @, the location line is omitted. Folder names support YYYYMMDD,
YYYY-MM-DD, YYYY.MM.DD, and YYYY年MM月DD日, with calendar-valid dates.
Subfolders inherit their nearest dated ancestor; image filenames and EXIF do not
replace this curated date. Synology #recycle, hidden folders, and @eaDir are
excluded. Extremely long captions shrink and then truncate visually; full values
remain available in catalog metadata.
Output is 1200×1600: a 1200×1280 photo area plus a white caption area. Original
files remain unchanged. Contain/cover/smart and color/grayscale profiles still apply.
A prepared source definition is in deploy/organized-photos-source.json; use it
with PUT /api/v1/photo-sources/organized-photos after mounting the library.