Configuration
You can configure the app via configuration.yaml
.
The location of the file depends on your installation method, see Quick Start.
Minimal Example
The following is a minimal configuration.yaml
example, see Defaults for all options.
yaml
collections:
# Normal Album-type collection
- name: Vacation Photos
dirs:
- /photo/vacation-photos
# Timeline collection (similar to Google Photos)
- name: My Timeline
layout: timeline
dirs:
- /photo/myphotos
- /exampleuser
# Create collections from sub-directories based on their name
- expand_subdirs: true
expand_sort: desc
dirs:
- /photo
Defaults
yaml
# Defines collections / albums that are scanned and shown in the UI
collections:
# By default show all subdirs of the current working directory
- expand_subdirs: true
expand_sort: desc
dirs: ["./"]
# - name: Collection Name
# layout: album | timeline | wall
# limit: integer number of photos to limit to (for testing large collections)
# expand_subdirs: true | false (expand subdirs of `dirs` to collections)
# expand_sort: asc | desc (order of expanded subdirs)
# dirs:
# - /first/dir
# - /second/dir
# - C:/third/windows/dir
# - ./relative/dir
#
# Later collections override earlier ones with the same name / id
# so that you can have expanded collections and override settings
# of specific collections.
# Default layout of all collections
layout:
type: ALBUM
render:
# The area at which photos are rendered as a solid color.
# The larger it is, the faster rendering will be, but also the more you will
# have to zoom in to see the photo and not just a single solid color.
max_solid_pixel_area: 1000
# Default tile size, the UI controls this directly, so it's only relevant for
# other use-cases.
tile_size: 256
ai:
# Host of an AI server providing machine learning features. Defining this
# will enable search functionality on collection pages.
# See https://github.com/SmilyOrg/photofield-ai on how to set it up
#
# host: http://localhost:8081
#
# You can also define the visual (image scanning) host and the
# textual search host separately, e.g. to scan images with a PC w/ GPU,
# but keep the search part on a NAS.
#
# visual:
# host: http://localhost:8081
# textual:
# host: http://localhost:8081
tags:
# Enable tagging support in the UI.
# Tags are currently only stored in the (cache) database, so they will
# be lost if it's deleted. Consider this alpha-level functionality.
#
# enable: true
# exif:
# enable: true
geo:
# Reverse geocode coordinates to location names. Runs fully locally
# via the "rgeo" Golang library. Currently only supported in the
# timeline layout.
#
# Can delay startup by up to a minute as the local geolocation
# database is loaded.
#
reverse_geocode: true
geopackage:
# Path to the GeoPackage file containing features
# WKB and TWKB (via tinygpkg) are supported.
#
# See https://github.com/SmilyOrg/tinygpkg-data
#
# If empty, the database embedded into the executable
# via embed-geo.go is used.
#
# path: data/geo/geoBoundariesCGAZ_ADM2_s5_twkb_p3.gpkg
# Table in the GeoPackage file to be used in case there is
# more than one
#
# If empty, the first table is used.
#
# table: globalADM2
# The column to use for reverse geocoding the location name
name_col: shapeName # geoBoundaries CGAZ
# name_col: name_conve # Natural Earth urban areas
# name_col: NAME_LONG # Natural Earth countries
media:
# Extract metadata from this many files concurrently
concurrent_meta_loads: 8
# Extract prominent colors from this many files concurrently
concurrent_color_loads: 4
# Extract AI embeddings from this many files concurrently
concurrent_ai_loads: 8
# Number of exiftool instances to run concurrently for metadata extraction
exif_tool_count: 4
# Set to true to not extract any metadata or colors from photos
skip_load_info: false
# Skip printing the file count of collections at startup
# This can speed up startup time for large collections
skip_collection_counts: false
caches:
image:
# Size of the image cache used while rendering images
# A larger cache might make display/rendering faster, while a smaller
# cache will conserve memory.
max_size: 1024Mi
# File extensions to index on the file system
extensions: [
".jpg", ".jpeg", ".png", ".avif", ".bmp", ".pam", ".ppm", ".jxl", ".exr", ".cr2", ".dng",
".mp4",
]
# Used to extract dates from file names as a heuristic in case of missing or
# metadata or metadata yet to be loaded.
# Uses the Golang date format: https://pkg.go.dev/time#pkg-constants
date_formats: ["20060201_150405"]
images:
# Extensions to use to understand a file to be an image
# extensions: [".jpg", ".jpeg", ".png", ".gif"]
extensions: [".jpg", ".jpeg", ".png", ".avif", ".bmp", ".pam", ".ppm", ".jxl", ".exr", ".cr2", ".dng"]
videos:
extensions: [".mp4"]
#
# Media source configuration
#
# Configures the different ways to load originals, photo variants,
# thumbnails, transcoded images, etc. For each photo, during loading or
# rendering, the most appropriate source is selected. The criteria include
# desired and expected dimensions, expected loading time, and possibly others.
#
# As a result, this configuration can have a large effect on the speed of
# the application.
#
# The following source types are supported:
# SQLITE, GOEXIF, THUMB, IMAGE, FFMPEG
#
# Common properties include:
#
# type: Case-insensitive source type (see above)
#
# extensions: File extensions supported by this source - the source will be
# skipped during selection if unsupported
#
# width, height: Expected dimensions of the provided images. These can be
# approximate in case it's not possible to know them upfront.
# Used during source selection to decide which source to pick.
# Some sources can have either hard-coded dimensions (e.g. sqlite)
# or assume the dimensions of the source file instead (e.g. image).
#
# fit: Aspect ratio fit of the provided image in case it doesn't match the
# original file. Not supported by all sources.
#
# INSIDE
# The thumbnail size is the maximum size of each dimension, so in case
# of different aspect ratios, one dimension will always be smaller.
#
# OUTSIDE
# The thumbnail size is the minimum size of each dimension, so in case
# of different aspect ratios, one dimension will always be bigger.
#
# ORIGINAL
# The size of the thumbnail is equal the size of the original. Mostly
# useful for transcoded or differently encoded files.
#
#
# Additional per-source properties are:
#
# SQLITE - internal thumbnail database
# type: sqlite
# path: File path relative to the data dir of the sqlite database containing
# the thumbnails
#
# GOEXIF - thumbnails embedded in JPEG EXIF metadata
# type: goexif
#
# IMAGE - native image loading
# type: image
# width, height: Resize the image after loading (can be slow)
# extensions: Supported source file extensions
#
# THUMB - pregenerated thumbnail files
# name: Short thumbnail type name
# path: Path template where to find the thumbnail
# {{.Dir}} is replaced by the parent directory of the original photo
# {{.Filename}} is replaced by the original photo filename
#
# FFMPEG - transcoded images via FFmpeg
# width, height: Dimensions to which the source media should be resized
# fit: The aspect ratio fit to use while resizing
# path: Path to the FFmpeg binary, uses the one in PATH if not set
#
source_types:
sqlite:
path: photofield.thumbs.db
cost:
time: 6ms
goexif:
extensions: [".jpg", ".jpeg"]
width: 256
height: 256
fit: "INSIDE"
cost:
time_per_original_megapixel: 670us
image:
extensions: [".jpg", ".jpeg", ".png"]
cost:
time_per_original_megapixel: 71ms
thumb:
fit: "INSIDE"
cost:
time_per_resized_megapixel: 70ms
ffmpeg:
fit: "INSIDE"
cost:
time_per_original_megapixel: 220ms
sources:
# Internal thumbnail database
- type: sqlite
# Embedded JPEG thumbnails
- type: goexif
# Native image decoding
- type: image
#
# Synology Moments / Photo Station thumbnails
#
- name: S
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_THUMB_S.jpg"
extensions: [".jpg", ".jpeg", ".png", ".gif", ".mp4"]
fit: "INSIDE"
width: 120
height: 120
cost:
time_per_resized_megapixel: 89ms
- name: SM
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_THUMB_SM.jpg"
extensions: [".jpg", ".jpeg", ".png", ".gif", ".mp4"]
fit: OUTSIDE
width: 240
height: 240
cost:
time_per_resized_megapixel: 70ms
- name: M
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_THUMB_M.jpg"
extensions: [".jpg", ".jpeg", ".png", ".gif", ".mp4"]
fit: OUTSIDE
width: 320
height: 320
cost:
time_per_resized_megapixel: 66ms
- name: B
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_THUMB_B.jpg"
extensions: [".jpg", ".jpeg", ".png", ".gif"]
fit: INSIDE
width: 640
height: 640
cost:
time_per_resized_megapixel: 42ms
- name: XL
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_THUMB_XL.jpg"
extensions: [".jpg", ".jpeg", ".png", ".gif", ".mp4"]
fit: OUTSIDE
width: 1280
height: 1280
cost:
time_per_resized_megapixel: 35ms
#
# Synology Moments / Photo Station video variants
#
- name: FM
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_FILM_M.mp4"
extensions: [".mp4"]
fit: OUTSIDE
width: 720
height: 720
- name: H264
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_FILM_H264.mp4"
extensions: [".mp4"]
fit: ORIGINAL
#
# FFmpeg on-the-fly decoding
#
- type: ffmpeg
width: 256
height: 256
fit: INSIDE
cost:
time_per_original_megapixel: 120ms
- type: ffmpeg
width: 1280
height: 1280
fit: INSIDE
cost:
time_per_original_megapixel: 160ms
- type: ffmpeg
width: 4096
height: 4096
fit: INSIDE
cost:
time_per_original_megapixel: 180ms
# These sources are used for handling small thumbnails specifically for
# specific purposes.
thumbnail:
# Thumbnail sources used for extracting colors and AI embeddings
# 200 - 300px is likely ideal as it's small enough to process quickly,
# but big enough to retain some details.
#
# The sources here are ordered and the first source that returns
# a valid image is used.
sources:
# Internal thumbnail database
- type: sqlite
# Synology Moments / Photo Station thumbnail
- name: SM
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_THUMB_SM.jpg"
extensions: [".jpg", ".jpeg", ".png", ".gif", ".mp4"]
fit: OUTSIDE
width: 240
height: 240
# Embedded JPEG thumbnails
- type: goexif
# Synology Moments / Photo Station thumbnail
- name: S
type: thumb
path: "{{.Dir}}@eaDir/{{.Filename}}/SYNOPHOTO_THUMB_S.jpg"
extensions: [".jpg", ".jpeg", ".png", ".gif", ".mp4"]
fit: "INSIDE"
width: 120
height: 120
# If a thumbnail is not found among the sources above,
# it is generated with the first working generator.
generators:
# FFmpeg decoding
- type: ffmpeg
width: 256
height: 256
fit: INSIDE
# Native decoding (resized to 256px x 256px)
- type: image
width: 256
height: 256
# The sink is used to save the generated thumbnail above
# so that it persists and can be reused while rendering.
sink:
type: sqlite