Files
pigway-frame-flow/docs/PHOTO_SOURCES.md
T

8.9 KiB
Raw Blame History

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
# Optional: existing NAS group allowed to read that folder (check its ACL).
# NAS_PHOTOS_GID=101

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. If the Synology ACL grants a group access, set NAS_PHOTOS_GID to that existing group ID; the optional Compose overlay adds only container group membership, keeping UID 10333 and the photo bind mount read-only. Group 101 is a deployment example, not a universal default. Frame Flow does not change NAS permissions. Unreadable roots return an explicit HTTP 403 rather than an empty catalog. 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-sources
  • PUT /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.

For Synology Photos shared libraries, synology_previews: true allows images over 20 MiB to use their existing @eaDir/<filename>/SYNOPHOTO_THUMB_XL.jpg preview. This is a read-only fallback: original files and Photos indexes remain unchanged, no thumbnails are generated on the NAS, and the ordinary size limit still applies to the selected preview. The catalog marks these entries provider_preview: true. If the preview is missing, the oversized original remains excluded. The folder caption still comes from the original curated directory.

Synology Photos 人物筛选 / People filtering

可选的只读集成使用 Synology Photos 共享空间的人物识别结果,不运行新的识别模型,也不修改人物分组或照片。个人空间暂不支持。

  1. 将共享图库(如 /volume1/photo)挂载为 /photos,保持只读。
  2. 在 .env 配置 SYNOLOGY_PHOTOS_URL=https://NAS_IP:9115 和 SYNOLOGY_PHOTOS_CERT_SHA256(服务实际 TLS 证书的 SHA-256 指纹,从可信 NAS 配置核实)。重建容器后生效。指纹变化时必须重新核实;每次连接在发送登录信息前校验同一个 TLS socket 的证书。
  3. 照片数据源 → 编辑数据源 → 连接 / 选择人物。管理员输入 NAS 用户名、密码;只保存 session 到 /config/synology-photos-session.json(0600),不保存密码。会话过期后需要重新连接;断开连接删除本地 session。页面没有 password/token 回显。
  4. 选择人物,启用筛选,选择“任意”或“同时包含所有”。默认只列出已命名人物,可搜索 ID、展开未命名分组。至少选择一个人物。
  5. 与当前本地目录、日期文件夹规则取交集,再随机选图。原文件夹标题、日期、地点仍保留。不匹配返回空图库;预览 / 定时任务失败,不回退到全图库。

接口:GET/POST/DELETE /api/v1/integrations/synology-photos(管理员);GET /api/v1/integrations/synology-photos/people(管理员)。Source 新增 people_filter、person_ids、person_match: any|all。普通图片读取权限只能使用已配置数据源,不能登录或查询人物目录。

只允许 Auth login/logout、共享空间 Person.list、Item.list、Folder.get。人物照片按 500 条分页,成员路径缓存 15 分钟,源目录缓存 60 秒;显式刷新会重新查询。无后台高频轮询,不下载全图库原图。查询失败和登录失效明确报错。大型人物相册首次查询可能需要数十秒。

This optional integration reads the existing shared-space People catalog. It does not modify Photos or perform face inference. Login stores only a protected session, never the NAS password. Certificate pinning happens before credentials are sent. Select one or more people and match any/all, intersect with the existing curated folder rules, then randomize. Empty matches and expired sessions fail closed. Person membership caches for 15 minutes; explicit refresh re-queries. This improves relevance, not blur/closed-eye detection. Recognition can miss faces. Personal-space filtering and automatic photo-quality scoring are not implemented.