2023 PhotoStructure release notes
Note that these are notes for versions released in 2023.
Please see the current release notes.
v2023.12.0-alpha.7 π
Released 20 December 2023
-
β¨ Sync reports now include reasons why the sync work queues may not consider themselves eligible to start more work. This could be from the system load being to high, or one of the critical health checks failing (like if a library volume has insufficient disk space). Sync reports also now auto-collapse repeating messages, so you don’t get thousands of lines of the same error message.
-
π Fixed “failed to apply SQL” error on Windows
-
π If “Scan all directories on all drives” is selected on macOS, we now avoid scanning
/
, with the belief that macOS users will typically store their files either in their home directory, or on external volumes. If you have files on your root partition outside your home directory, you can always add them explicitly, and PhotoStructure will scan those paths even if “Scan all directories on all drives” is selected. -
π
sync
schedules a cleanup process after every 50 processed files. Unfortunately, this cleanup process would force-rebuild theTag.assetCount
column in prior builds. Force-rebuilding this column can take 10 or more minutes on slow machines and large libraries. The “cleanup” no longer force-rebuildsTag.assetCount
, as it is kept up to date incrementally as assets are added or removed from tags.
v2023.12.0-alpha.6 π
Released 17 December 2023
- π Reverted alpha.5
WorkQueue
job dequeuing tweak (as it seemed to cause lower cpu systems to never do work)
v2023.12.0-alpha.5 π
Released 17 December 2023
-
π Fixed PhotoStructure for Node on Windows to find tooling like SQLite. Thanks for reporting, @mackid1993!
-
π Fixed macOS
./start.sh
error iftimeout
was missing (rather than requiring users tobrew install coreutils
). Thanks for reporting, @Zandr! -
π Database validation would fail if the database was locked. We now retry each validation step if we get lock errors. See the
maxBusyDbMs
setting for details. -
π¦ On Windows we now add
%ProgramData%\chocolatey\bin
as a backfill%PATH%
entry (to help findffmpeg.exe
). Thanks for reporting, @Leaky! -
π¦ Prior builds relied on the
ffmpegPath
setting to be resolvable. We now use thepathTo()
function (which includes backfill default paths) for allffmpeg
commands -
π¦ Added the current userid/groupid to the library directory health check message to simplify finding the correct PUID/PGID values.
-
π¦ Added
toolsDir
,osToolsDir
,ffmpeg
, andsqlite
paths tophotostructure info
to aid in future debugging -
π¦ Added
jpegtran
health check. You know you all wanted it. -
π¦
WorkQueue
job dequeuing tries to take into account system load to avoid overscheduling
v2023.12.0-alpha.3 π
Released 17 December 2023
Database improvements π
-
β οΈ We now use SQLite’s STRICT mode, but this requires your library database to be completely dumped and reloaded. This happens automatically, but expect larger libraries to take up to a minute to start after upgrading to this build, depending on the speed of your server and disk.
-
β¨/π¦ Tag asset counts are now updated in real time, as assets are imported. This should avoid CPU and
IOWAIT
stalls during syncs for users with large (100k+) libraries, as we don’t have to do large bulk updates to the tags table during sync runs. -
π¦ The fulltext search index for tags is now incrementally updated only on Tag creation. Prior versions rebuilt the entire index whenever “database maintenance” was scheduled, which, in some cases, could lead to SQLite errors if multiple FTS rebuilds occurred simultaneously.
Docker improvements π
-
π Fixed docker detection regression from
alpha.1
. See the forum for details. Thanks for the report, @underdog! -
π¦
:alpha
docker builds now overwrite:prealpha
builds -
π¦ Configured image publishing to GHCR. This is in addition to publishing to Docker Hub.
Metadata extraction improvements π
-
β¨ The XMP Album tag is now extracted from photos and videos. The existing
tagAlbumTitle
(AKAPS_TAG_ALBUM_TITLE
) setting now accepts multiple values. -
β¨ The MWG Collections tag is now extracted from photos and videos for Albums, as well. As these are regularly hierarchical, the default for
tagAlbumTitleHierarchies
has been changed totrue
. -
π When extracting orientation, we no longer fallback to
.CameraOrientation
. The image may have been rastered with a different orientation since being captured which means this orientation may not be relevant anymore. This resulted in images that were stretched in asset views, or incorrectly rotated in tags. -
π Prior CapturedAt extractions can be written to sidecars when copying files into your PhotoStructure library, which can preserve sibling metadata. A couple defects were found and addressed:
-
Some date formats, like DateIntervals, were not parsed properly and inhereted by subsequent metadata extraction runs, and could cause
sync
errors (likeTypeError: t.capturedAt.toAssetFileFields is not a function
) that caused those file to not be re-importable. Thanks for reporting this, @mackid1993! -
Sidecars whose names were applicable to multiple filenames could include (unrelated) prior captured-at values. We now exclude mismatching basenames from subsequent inheritance.
-
-
π/π¦ PhotoStructure now writes rotation metadata to both
.Orientation
as well as.Rotation
for both images and videos. Several camera manufacturers write to both tags, and this ensures correct orientation regardless of where other applications look for orientation metadata. -
π¦ Related: the new default for
sidecarTagBlocklist
is["Orientation", "Rotation", "Rating"]
, as almost no software knows to look in sidecars for these fields. -
π¦ If metadata tags the GPS location to be (0,0), that will be ignored (as it’s in the middle of the ocean).
-
π¦ Added
DateTimeUTC
andGPSDateTime
tocapturedAtTagsFallback
-
π¦ ExifTool upgraded to v12.70. π Thanks for 20 years of updates, Phil Harvey! π
Privacy improvements π
-
π¦ Added alias for
PS_OPT_OUT
environment variable,DO_NOT_TRACK
: when set to something “truthy”, all code that makes external network requests (like error reporting and version checking) is disabled. -
π¦ The
autoUpdateCheck
,allowUserAgent
, andreportErrors
settings now default tofalse
in code, but default totrue
on the settings page. This means these features are disabled until the user has a chance to decide how they want to configure their system -
π Fixed persistence of the new
allowUserAgent
, andautoUpdateCheck
values on the settings pages (thanks for reporting, themk!)
Video improvements π
-
π¦ Fixed version parsing for FFmpeg v6.1 and validated screen grabs and transcoding for >10 different video formats, but if you see videos not playing, please report any glitches or bugs to the forum or discord!
-
π¦ The
ffmpegScaleType
setting has been deleted. FFmpeg reliably applies the “old-style”-s WxH
resize setting reliably, and some versions don’t accept the “new-style”-vf scale
format, which doesn’t seem to be any faster, so we’ll just stick with-s WxH
.
General improvements π
-
β¨ Desktop builds are now available. Please report any issues to the forum or discord!
-
π If the
web
service can’t bind to the web port, themain
service now properly shuts down and relays the error to the terminal. Prior builds would retry spawningweb
indefinitely, which was confusing. -
π The about page no longer includes “undefined” for the user id or group id on Windows (users don’t have numeric ids on Windows)
-
π Fix TOML output for multi-line and string values that exceed 80 characters. Prior builds’ word wrapping could cause invalid settings.toml output.
-
π If
validationErrorAllowlist
was set to an empty set, prior builds ignored all file validation errors. (Who knew that JavaScript replaces empty RegExp with/(?:)/
, which matches everything?) Empty sets are now mapped to/$^/
, which matches nothing. -
π Fixed
esc
handling after hide/exclude/trash. Thanks for the bug report, Leon! -
π/π The
retainFileBirthtimes
setting was removed, as theutimes
native dependency current version has an unfixed memory retention flaw. This means the best-effort attempt to retain copied file “birthtimes” will no longer be applied. -
π¦ PhotoStructure for Node’s
./start.sh
now runsgit pull
with a one minute timeout, so if it runs before the network is set up (or external network requests hang), it will eventually try to start. -
π¦ Upgraded Electron to v27, which includes Node 18 (upgraded from Node 16). As always, please report any glitches or bugs to the forum or discord!
-
π¦
./photostructure info --version-check
now rendersinstalledVersion
,installedChannel
,latestVersion
, andlatestChannel
(which should be helpful for debugging) -
π¦ PhotoStructure “cleanup” tasks now prune database backup directories, sync reports, and hot-backup directories. See
dbBackupRetentionCount
andsyncReportRetentionCount
settings for details. -
π¦ Tool versions on Linux distributions that use
pacman
(like Fedora and Arch) are now provided bypacman -Qo
. -
π¦ Added
--timing
to all tooling, which emits performance metrics collected during a run to stdout on exit -
π¦ Added
--tags
to thelist
tool to render all tags and their asset counts -
π¦ Settings that reference field names all consistently use a new case-insensitive “pluckDeep” function now (so, for example, the
tagAlbumTitle
setting can includeCollections.CollectionName
, and have it work)
v2023.11.0-alpha.1 π
Released 7 November 2023
π/π Exclusion globs have been simplified π
-
Exclusion glob patterns are now applied both in and out of libraries: the
excludeGlobsInLibrary
setting (introduced last build) was confusing, and has been deleted. -
The
disableIgnorableFilters
setting was renamed toomitDefaultExcludeGlobs
, but does the same thing: if set totrue
, users start with an empty set of exclusion globs, and useexcludeGlobsAdd
to build up whatever set of patterns they want.
Additional improvements π
-
π Video transcodes in prior builds had a 2 minute timeout (due to a misapplication of a default argument), which would slow down larger video imports because transcode operations would timeout incorrectly and retry (causing the system to bog down with the same ffmpeg operation multiple times)
-
β¨
ffmpegHwaccel
can now be safely kept atauto
–PhotoStructure will attempt the transcode with-hwaccel=auto
, but if that fails (due to missing hardware support for the necessary codecs, for example), we’ll automatically re-try that transcode operation without a-hwaccel
argument. -
π
Asset.durationMs
is now properly copied from AssetFile variations up to Asset. Prior builds could have missing duration timestamps in tag galleries.Note that this is backfilled partially by a database migration that will be applied automatically, as well as a step that invalidates all asset files (and assets) that are videos and missing
.durationMs
. -
π Fixed
./start.sh
warnings and errors related to pythondisttools
andsetuptools
-
π Fixed version health check bug where running a newer version than what is advertised as being available was marked as being “out of date”. Also added channel advice if a more stable channel is providing a newer release.
-
π¦
./photostructure info --version-check
is now a whole thing, and invalidates prior cache. -
π¦ Open Graph headers were simplified: we now only send one video or image entry, using the closest available prerender to
openGraphTargetWidth
. Previews seem to work properly now at least on Apple iMessages. -
π¦ New
checkBasenameMatches
setting (defaults to true) adds Yet Another asset file’s existing-asset adoption search strategy. This is a minor deduplication improvement, and doesn’t seem to adversely impact import speed. -
π¦ Docker images now include a proper set of labels:
"Labels": {
"org.opencontainers.image.created": "2023-11-07T21:28:51.769Z",
"org.opencontainers.image.description": "PhotoStructure for Servers",
"org.opencontainers.image.licenses": "NOASSERTION",
"org.opencontainers.image.revision": "f98e5a7e0f115fbf415511952e004e4a82c212a2",
"org.opencontainers.image.source": "https://github.com/photostructure/photostructure-for-servers",
"org.opencontainers.image.title": "photostructure-for-servers",
"org.opencontainers.image.url": "https://github.com/photostructure/photostructure-for-servers",
"org.opencontainers.image.version": "2023.11.0-alpha.1"
}
v2023.11.0-prealpha.19 π
Released 2023 November 2
-
π File hidden tests no longer run on drive letters on windows (
C:\
is reported to be hidden as perGet-Item
) -
π Fixed PowerShell health check on Windows
v2023.11.0-prealpha.18 π
Released 2023 November 2
β¨ Version checking was added as a health check π
PhotoStructure can now make periodic requests to https://photostructure.com/channel-versions.json, using a User-Agent that exposes
- The version of PhotoStructure that you’re using (
PhotoStructure/2023.10.0
) - Your operating system and system architecture (like
Windows 11 on x64
orUbuntu 22.04.3 LTS on x64
) - Your current subscription (
PLUS
orLITE
)
Several new settings were added to let you suit this feature to your taste:
-
A new section in the Settings page lets you disable either the version check altogether, or just the custom user agent
-
By setting
PS_AUTO_UPDATE_CHECK=false
, which disables version checks, or -
By setting
PS_ALLOW_USER_AGENT=false
, which makes theUser-Agent
be simplyPhotoStructure
, or -
By opting out of all external network requests with the new meta-setting,
PS_OPT_OUT=true
, which changes:- the default value of
PS_AUTO_UPDATE_CHECK
to false - the default value of
PS_ALLOW_USER_AGENT
to false, and - the default value of
PS_REPORT_ERRORS
to false
In the future, when there are any other features in the future that may require external network requests, those will be disabled by default with this meta setting as well.
- the default value of
Video improvements π
-
π VLC support has been dropped. Please use FFmpeg instead. Setup instructions were updated for every platform.
-
π Depending on how video files were encoded, metadata (like the video duration) could have been missing in prior builds. PhotoStructure now properly omits the
-fast
argument when reading and extracting video metadata. This bug could have caused videos to not be imported in prior builds, or video transcode timeouts to be (very) incorrect. -
π
(this change was reverted in v2023.11.0-alpha.2).ffmpeg
transcode rescaling could fail on older versions, causing videos to not be imported. We now try the new-style-filter:v scale=WIDTH:HEIGHT
format, and automatically downgrade to the older style-s WIDTHxHEIGHT
argument format if there are errors. See the newffmpegScaleType
setting for details: -
π
ffmpeg
transcoding now supports bounded framerates. See the newtranscodeFrameRate
setting for details:
If set, transcoded videos will be bounded to this framerate. Videos that are lower than this framerate will retain their original (lower) framerate.
Note that framerate reduction does not reduce the final transcoded video size linearly: it may only reduce file sizes by ~20% to go from 60 FPS to 30 FPS.
Unset this or set to 0 to disable bounded framerates.
- π Video timezone parsing has been improved
Additional changes and improvements π
-
β¨ Asset pages are now rendered with OpenGraph header metadata. See the forum for details.
-
π Image rotation was broken for some orientations in prior builds. We now only consider rotations that match the exemplar aspect ratio. The final rotation formula was simplified and (more) tests were added as well.
-
π
sync
re-scheduling in prior prealpha builds would only happen if mountpoints had changed–now there is no such prerequisite condition. -
π Very large values of
PS_MAX_MEMORY_MB
will no longer result in very few worker processes. -
π More recent Panasonic camera RAW images can now be imported by PhotoStructure, with the addition of the new
validateMimetypeSkiplist
setting, and addingJpgFromRaw2
to the default set of theembeddedPreviews
setting. -
π PhotoStructure tried to look at Linux
cgroup
files for CPU scheduling, but the implementation proved to be incorrect on many systems. PhotoStructure now relies on availableParallelism. If that isn’t available, PhotoStructure counts the CPUs returned by os.cpus(). See the forum post for more details (thanks for the assist, @underdog!) -
π The
assetPathnameFormat
setting in prior builds was stripped of all quotes, which resulted in static strings incorrectly being interpreted as path tokens. -
π¦ Thumbnail and video serving by the web service is now more tolerant of incorrect/unavailable resolutions: PhotoStructure will 302-redirect to the nearest resolution preview now.
-
π¦
PS_LOG_SERVER_LEVEL
now defaults to the value ofPS_LOG_LEVEL
if unset. -
π¦ Added version extraction backstop for Debian/Ubuntu external tooling (mostly for
heif-convert
debugging). -
π¦ PhotoStructure can now use
dpkg -S
to check for installed versions of tools on Debian-based systems (which will help debug issues withffmpeg
andheif-convert
). -
π¦ EXIF dates can be partially specified–month and day that is set to two spaces is considered “unset”, so “2023: : " or “2023:00:00” is considered to just be the year 2023. See the forum for details.
-
π¦ Timezone offsets (like “+5” or “-07:00”) are now optionally extracted and respected for all date formats, including fuzzy date formats.
-
π¦
extraDateTimeFormats
now includes additional formats to extract timestamps from filenames from LG, dashcam, and action cameras. -
π¦ Added operating system version health check (to make it clear we didn’t support end-of-life OSes or Linux distributions that aren’t Ubuntu, Debian, or Fedora), and removed the version check from
./start.sh
. -
π¦ Health checks now warn against ancient versions of
ffmpeg
andheif-convert
(if version metadata is available). -
π¦
backfillTimezones
andinferTimezoneFromDatestamps
are now exposed by settings and enabled by default. See the documentation for details. -
π¦ ExifTool
MWG
mode is now enabled by default. See the newuseMWG
setting to revert to prior behavior. See https://exiftool.org/TagNames/MWG.html for details. -
π¦ On Windows,
%SystemDrive%\cygwin64\bin
is now checked for external tooling even if it’s not in the%PATH%
-
π¦ Improved make/model handling for several new flagship mirrorless cameras
-
π¦
info
improvements:- Added PhotoStructure version metadata (including available updates for the current channel)
- For given files, why (if at all) the file would be rejected from being imported
- For given files, include all inferred metadata (like captured-at time, timezone, make, and model)
-
π¦ File and directory exclusion globs can now conditionally applied, depending on if files are in your library or originals directories. If the new
excludeGlobsInLibrary
setting istrue
, prior exclusion glob application behavior will be in place, and if a library directory happens to match an exclusion glob, we won’t import any files (!!). The default for this setting isfalse
, which means we won’t skip over files that match exclusion globs that are in the library or originals directory hierarchy. Note that files in NoMedia folders and hidden files (that start with.
) are still be ignored. -
π¦ Pulled in latest third-party libraries, including SQLite and ExifTool
-
π‘οΈ Added a regex linter to the build pipeline, and fixed several issues (including a couple that could result in super-linear backtracking)
v2023.9.0-prealpha.17 π
Released 2023 September 9
-
π Prior video transcoding timeouts were validated against .MOV and other older video formats. HEVC in 4K 60fps require 10x the CPU time, based on bytes to transcode–so prior builds would erroneously timeout video transcode operations and then retry, causing imports to crawl to a halt (and burn CPU time needlessly). The following fixes are in this build:
- Video asset file imports now have no timeouts. I may reestablish this timeout in the future if we find people’s sync getting “stuck” in
ffmpeg
, but I don’t have a record of that. - The “is this previously transcoded file” test assumed a transcoded file would not be less than a quarter the size of the original file–but if we’re downsampling videos, this limit isn’t correct. The expected file size is now (duration * bitrate), and a transcoded file can now be validly 10% of that size without requesting a new transcode.
- Video asset file imports now have no timeouts. I may reestablish this timeout in the future if we find people’s sync getting “stuck” in
-
π CPU rendering code would return
undefined
for values higher than 100%–which would normally be a reasonable approach, but PhotoStructure uses an average of load and cpu usage statistics–if system load is higher than current CPU count, “busy percent” will exceed 100%. -
π Pulled in new exiftool-vendored build which avoids invalid datetime values from some cameras (like “00” and “01”, which prior builds would consider an obscure ISO reference to today’s date). Those invalid values are now properly ignored.
-
π¦ A new “share” icon was added to the asset header, but most browsers do not support sharing embedded
blob
-based files, so most people won’t see the icon :sob: (you can still long-press the asset image and share that, though)
v2023.9.0-prealpha.16 π
Released 2023 September 7
-
π Fixed
cpuUsage()
bug that could cause it to stay atundefined
-
π Invalid values (like “00” and “01”) associated to EXIF
SubSec
datetime fields could assume the current date (!!). This is now fixed. -
π The CPU busy code was incorrectly filtering all values (!!), which led to the
undefined
cpu percent in the health check -
π¦ Adjusted
maxCpus()
to account forsync
load to more accurately schedule the correct number of import jobs -
π¦
SystemLoadHealthCheck
now refreshes every minute -
π¦ Current system load was added to the
/about
page -
π¦ CPU count now uses
node:os.availableParallelism()
if available (Node.js v18+), and on Linux,/sys/fs/cgroup/cpu/cpu.cfs_quota_us
,/sys/fs/cgroup/cpu/cpu.cfs_period_us
, and/sys/fs/cgroup/cpu/cpu.shares
are taken into account. The least value from all these methods is used for the “CPU count.”
v2023.9.0-prealpha.15 π
Released 2023 September 6
-
π Fixed
ffmpeg
overscheduling by moving the--threads
argument after the input. The default value for--threads
remainsclamp(1, 8, $PS_FFMPEG_THREADS ?? maxCpus() / 2)
, wheremaxCpus()
is$cpuCount * PS_CPU_LOAD_PERCENT
. -
π Fixed CPU utilization health check to refresh when a proper cpu load value was available.
-
π
sync
will now runMath.max(1, maxCpus() - 1)
workers. Previously it would schedulemaxCpus()
workers, which could result in overscheduling (especially on CPUs with only 1-4 threads)
v2023.9.0-prealpha.13 π
Released 2023 September 6
-
π Search
when:2023
didn’t work (thanks for the report and assistance, @avdp and @tkohhh) -
π When rotating images with prior versions,
-Orientation
would always be delivered to sidecars (because thePS_SIDECAR_TAG_BLOCKLIST
includedOrientation
, but we have to pass-Orientation#
to ExifTool). Unfortunately, nothing respects sidecarOrientation
values, so it resulted in images not being rotated properly. Thanks for example, @tkohhh! -
π Found and addressed several codepaths that could throw “e.localBoundaries not a function”–JSON serialization for
Date
andDateTime
were broken. Thanks for the reports, @slothstronaut, @ltlowe, and @HelloPanic! -
π Images with
stat
-only captured-at date variants should have more consistent aggregation. Thanks for the report, @nuk! -
π Search
Keywords:___
is now a valid alias forkw:___
, which fixes the search result from clicking from keyword tags. -
π Improved dominant color extraction with arbitrary image rotations–images could be incorrectly dis-aggregated, especially for variants that were rotated by
Orientation
tag versus re-rastered with a different orientation. -
π PLUS licenses could fail to activate in some situations. This should be improved, but holler if you see an issue.
-
π The settings page’s library directory suggestions code could, in some situations, fail to suggest anything, resulting in an error. This was improved.
-
π Health check validation on
web
now only waits for “critical” health checks (like library database validation) before moving from the splash screen onto the home page. -
π Volume metadata results could be postponed for a fraction of the short command timeout on some Linux boxes if
gio
wasn’t installed. This was fixed. -
π
sync
is now properly restarted when settings are saved, which should fix “initial scan not starting on it’s own”–thanks for the report, @advp! -
π¦ Dropped
fsCache
for most codepaths–the mutex implementation proved to be problematic on some filesystems. Future versions may adopt a different caching strategy, but performance doesn’t seem to be dramatically impacted (especially on systems with fast disks). -
π¦ Third party libraries were upgraded, including sharp, SQLite, and ExifTool.
-
π¦
Error
stacktraces are included in log metadata, which may help expedite issue reproduction.
v2023.8.0-prealpha.12 π
Released 2023 August 28
- π¦ Skip
lsblk
on docker–the debian container doesn’t see any host volume UUIDs.
v2023.8.0-prealpha.11 π
Released 2023 August 28
-
π PhotoStructure for Docker now ignores the root partition,
/
, for both volume metadata and as a scan path. This was accomplished by changing the default for thePS_EXCLUDED_MOUNTPOINT_PATHS
setting to include"/"
by default on docker. Thanks for the suggestion, MK! -
π¦ Add wget to the docker image to satisfy the
HEALTHCHECK CMD
(thanks for the catch, @avdp!)
v2023.8.0-prealpha.10 (“Nighthawk TNG”) π
Released 2023 August 28
-
π Fix docker error in
docker-entrypoint.sh
by directlyexec
ingphotostructure.js
rather than using/usr/local/bin/node
-
π Fix spurious “No eligible files found in scanned paths”
-
π¦ Install
source-map-support
for better stacktraces
v2023.8.0-prealpha.9 (“Nighthawk”) π
Released 2023 August 28
- π¦ v23.8.0-prealpha.9 fixes the base debian image, adds a missing dependency on
type-detect
, and updates several other third party libraries.
v2023.8.0-prealpha.8 π
Released 2023 August 28
Note that prior prealpha builds were YY.MM.MINOR
, and after a discussion on Discord, we’re switching to YYYY.MM.MINOR
to make it clearer that the first number is a year.
-
β¨/π Deduplication improvements: see new
allowFuzzyDateImageHashMatches
setting. More details are in the forum. Thanks for your help, @nuk! -
π Docker setup on new instances was broken due to (several) health check bugs. This caused a redirect loop from the welcome page to the health check page (see discussion).
-
π Improvements to avoid overscheduling and timeouts:
- Health checks are now processed with a bounded concurrency queue, rather than all 35 checks running in parallel, which could cause spurious health check failures.
- Parts of
sync
’s file processing pipeline had used bounded concurrency queues in an effort to expedite completion. Unfortunately, this results in overscheduling, especially if assets have sidecars. The processing pipeline has been changed to always use serial processing to avoid this overscheduling, and rather than defaultingmaxConcurrentImports
to 50% of maxCpus, the new default is 100% of maxCpus. This should avoid overscheduling timeouts like this.
-
π Directory iteration had a step that examined sidecar eligibility in a tight loop, synchronously, which could cause spurious external timeouts when processing directories with many (1k+) sidecar files. Sidecars are now processed asynchronously in timed chunks (just like non-sidecars) to avoid this situation.
-
π
sync
memory consumption could grow to > 1GB on high CPU hosts. Memory allocation and retention was profiled and several hotspots were remediated, allowing for better GC of child process, weak, and lazy references, andsync
is back down to ~50MB, steady state. -
π¦ The base image for PhotoStructure for Docker is now node-20-bookworm-slim.
I initially based PhotoStructure for Docker off of Alpine because the Alpine base image size (181MB) was smaller than the Debian image base (245MB).
After installing all of PhotoStructure’s prerequisite libraries and tooling, though, the base tools images are quite comparable: Alpine is 619MB and Debian is 787MB.
Given this lack of substantial size benefit, Alpine suddenly looks less appealing:
- Supporting Alpine is Yet Another Platform that requires special codepaths in PhotoStructure and requires the test suite to be run in
- Several issues (including buggy RAW DNG image decoding) are only reproducible within Alpine, so just by moving to Debian, we “fix” the bugs
- The
ffmpeg
package in Debian supports several more codecs.
-
π¦ The library test suite is now runnable within docker. Test runs within docker in previous versions were limited to the core test suite.
v23.8.0-prealpha.7 π
Released 2023 August 11
-
π Fixed Windows volume status parsing (thanks for the assist, @mackid1993!)
-
π¦ Added log level and directory to the about page
-
π¦ Fixed font weight rendering and upgraded Roboto and Roboto Mono to latest versions thanks to Google Fonts Helper
v23.8.0-prealpha.6 π
Released 2023 August 10
-
π Remove spurious “missing volume UUID for
/
” on docker (details) -
π Attempt to fix FK error in Tag (details)
- disable Tag instance caching
- assign NULL values from the db back to the models
-
π¦ Downgrade levels for a heap of
.warn
and.info
logs
v23.8.0-prealpha.2-5 π
Released 2023 August 9
-
π Support
$PUID
and$PGID
values of 1000 (which collides with the docker imagenode
user and group) (details) -
π Upgrade Dockerfile to Node.js v20
-
π Disable
proc-not-superuser
health check on Windows by default: everyone always runs as an admin user. -
π Fix github actions to properly tag
:prealpha
builds
v23.8.0-prealpha.1 π
Released 2023 August 8
(This version’s contents had previously been listed as v2.1.0-alpha.8
, but we’re switching to CalVer, using scheme YY.MM.MINOR
.)
β¨ PhotoStructure no longer “fails fast.” π
What’s that mean?
PhotoStructure will try to always stay up and running, even if your library isn’t available, or something’s amiss, like a misconfiguration or something broken on the system.
If anything prevents your library from being open, PhotoStructure will automatically redirect to a new /health
page that list several handfuls of health checks to help people diagnose what’s amiss, and in some cases, buttons that can attempt to repair what’s wrong.
This means people running PhotoStructure for Docker without reading the instructions will be presented with a friendly screen with direct links to the relevant documentation.
This change also meant I could put the /about
page on a diet–it only holds fairly cheap and cached content now, so it shouldn’t disconcertinly hang anymore (prior versions ran several “health checks” that were run synchronously whenever the about page was requested).
This change also means PhotoStructure stays up even if your library hard drive gets periodically disconnected.
There are now more than 15 health checks which cover common setup issues, including
- file or directory permission errors
- missing volume UUIDs
- database schema validation
- misspelled or misconfigured settings
- external tool verifications
Read more about this change on the forum.
Note that any (and all!) health checks can be disabled with the new PS_SKIP_HEALTH_CHECK_IDS
setting.
β¨ SQLite improvements π
-
PhotoStructure now automatically figures out the best value for PS_FORCE_LOCAL_DB_REPLICA. Previously, we simply defaulted all docker installs to use a local db replica, whose implementation was problematic with prior versions. This determination is also run within a filesystem advisory lock, to prevent concurrent db setup collisions.
-
Database backups are now always taken “hot.” Prior versions required acquiring a halt-the-world mutex to prevent cold backups from causing SQLite corruption (and prior versions had some codepaths that didn’t acquire the lock durably). Prior versions could also miss copying over the
-wal
write-ahead log, which could also cause SQLite corruption. -
The new db health check now validates file integrity, foreign keys, and that the schema comprehensively matches expectations for the current version.
β¨ PhotoStructure for Desktops improvements π
-
The main window now preserves placement (even across screens) and dimensions between runs.
-
The
View
menu now has links to go back, open the log and sync reports directories, the systemsettings.toml
, and the librarysettings.toml
β¨ PhotoStructure for Servers improvements π
-
Docker and node editions now have a splash screen to see wth is going on at startup (without having to tail logs). (This page only shows if your library is quite large, your computer is quite slow, or a combination of both).
-
If PhotoStructure can’t open the current library, instead of crashing, a new “PhotoStructure Status” page will be shown with diagnostics to help debug what went wrong and links to how to fix it. This should be a lot more friendly (especially as a first impression) for most people.
-
PhotoStructure’s binaries and supporting files were moved from
/ps/app
to/opt/photostructure
. This move shouldn’t impact anyone, and was made to avoid people being confused by mounting anything to/ps
and hiding the entire installation.
β¨/π/ποΈ Image deduplication improvements π
-
Dominant color extraction now uses adaptive greyscale prefiltering, iterative k-means clustering, and returns percent coverage per color. This change required a database migration (that will be applied automatically) and a library rebuild (that will be scheduled automatically). See the new
dominantColorPixels
,dominantColorKmeansRuns
,dominantColorMergeThreshold
, anddominantColorGreyThreshold
settings. -
Prior builds relied on a single (mean) image hash algorithm. This build adds two additional, novel CIELAB-based approaches (gradient diff and DCT). Having 3 different hashes dramatically helps both precision and recall.
-
Image hashes now use higher-quality resizing interpolation.
-
New settings to control correlation thresholds:
minImageCoeffPct
,minColorCoeffPct
,imageHashFuzzyDateDelta
,imageHashFuzzyDateDelta
,imageHashRotationDelta
,imageHashDifferentMimetypesDelta
, andimageHashGreyscaleDelta
. -
When comparing two files, if either one of the files has an “imprecise” or “fuzzy” captured-at value (if the source is from the filename, inferred or from
Stats
), the image hash is always used, and the captured-at can be different. Disable this behavior by settingstrictDeduping=true
. Prior builds would skip the image hash comparison in some cases. This change will require libraries to be rebuilt when upgraded to this build.
β¨/π Time parsing improvements π
-
Video files are notoriously hard to get correct captured-at timezone offset values. Videos regularly encode the
CreateDate
tag in UTC (even when the file wasn’t captured in UTC!). This results in videos from prior versions of PhotoStructure being wrong by several hours. PhotoStructure now tries to “repair” the UTC timezone into the correct timezone by using either GPS metadata or a timezone offset inferrable via the filename. PhotoStructure also now has prioritized tag extraction: see thecapturedAtTags
and newcapturedAtTagsFallback
settings. Note that some Quicktime tags are not reliably stored as UTC, so we look for more reliable tags before resorting to these problematic tags. If you find a video doesn’t have the correct time in your PhotoStructure library, please email us an example. -
Timezone parsing has been improved to support both IANA and ISO offset formats (both of which have been found in the wild π ).
-
PhotoStructure handles missing timezones and differing timestamp precision more intelligently now: see
minCapturedAtPrecision
andfuzzyDatePrecisionCoeff
for explanations. -
Google Takeout JSON sidecar timestamps no longer (incorrectly) inherit the current system timezone.
Other improvements and bugfixes π
-
β¨ Tag galleries now support both square crops as well as aspect-respecting thumbnails. The toggle is in the upper right corner of all tag galleries.
-
β¨ Asset file aggregation is stricter. Previous versions of PhotoStructure attached file variations to existing assets as long as they matched any asset file associated to the asset. PhotoStructure will now aggregate new asset files only if they match all asset file variations. Set the new
assetAggregation
setting tounion
to restore prior behavior. -
β¨ Both Alpine and Ubuntu Docker images are now available. There are pros and cons to both images:
- Alpine images are less than half the size of the Ubuntu-based images
- Ubuntu’s
ffmpeg
package supports (many!) more video codecs - Ubuntu has better GPU acceleration support
- Performance between the two images is roughly equivalent
-
β¨
psnet:
asset file URIs now supportsshfs
-mounted partitions -
β¨ A new
transcodeMaxResolution
setting allows transcoded videos to not exceed a specific resolution threshold. See the forum post for details. -
β¨/π Prior versions on Windows and Raspberry Pi on slow disk could result in invalid file lock timeouts, which could prevent some file types (like large HEIFs) from being imported. This could show up as
EBUSY
orENOENT
errors in your sync report or logs. -
β¨/π Some camera models (like the Galaxy S8+) can produce images that have JPEG encoding errors. Prior builds would prevent importing of these images. (Thanks for the example images, @nighthawk!)
Handling these images required a couple changes:
-
A new setting,
imageFailOn
, lets you import images that have minor encoding defects by default, but still reject images that have been truncated. -
Default values for the image validation patterns,
validationErrorBlocklist
andvalidationErrorAllowlist
, now handle more corruption patterns.
-
-
π/π The
processPriority
setting no longer supportsAboveNormal
. If your settings used this value,processPriority
will resort to the default,Idle
.AboveNormal
only worked if PhotoStructure was running as root (which it never should do!) -
β¨/π¦ The
/site.webmanifest
file is now dynamically generated, and includes a properstart_url
(so every launch will pick a new seed) and defaults todisplay: fullscreen
. -
β¨/π¦
info
tool improvements:-
Image hash comparison information, including all correlations, deltas, and thresholds, are now included for files (which may help tune
imageHash*Delta
settings values). -
Dominiant colors now include friendly names and percent image coverage.
-
Limit output to only image hash metadata with the new
--image-hash
filter. -
pathToLibraryAsset
is now rendered for every file to help debug theassetPathnameFormat
setting. -
When given more than one file applies clustering on the entire array and will return the files provided to ARGV, grouped by asset.
-
Several additional switches were added to
info
to help customer support, including--read-settings
,--suggested-libraries
, and--child-env
.
-
-
β¨/π Files with extensions that don’t match their mimetype (say, JPEG-encoded images named
image.dng
, which Google Takeouts likes to do) are now imported gracefully. -
β¨/π
settings.toml
and.psenv
files are now read correctly when BOM-encoded as UTF-8 or UTF16-LE. -
π Glob exclusion patterns were not being applied correctly on Windows
-
π Newer linux distributions could pull in a version of
heif-convert
that has a buggy filename parser. PhotoStructure invokes this tool in such a way that this bug is avoided. -
π Prior builds would cache the absence of
heif-convert
until restart, which caused confusion for some users. PhotoStructure will now detect newly-installedheif-convert
binaries within a minute. -
π Fixed docker
:alpha
,:beta
, and:stable
tagging (see the simplified example) -
π Rewrote how tools (like
ffmpeg
,heif-convert
, andjpegtran
) are detected on the system. Rather than spawningwhich
, or asking PowerShell for the binary path, we now walk$PATH
looking for binaries withrx
access. If$PATH
is somehow truncated or invalid, we also walk some default paths (like%SYSTEMROOT%
on Windows, and/usr/bin
and/usr/local/bin
on macOS and Linux).This fixes
sqlite.exe not found
andjpegtran.exe not found
errors on Windows, and should fix SQLite backups on Windows. -
π Fixed o.toLocal is not a function, caused if an asset file fails to extact a captured-at time. (Thanks for reporting, @pmocek!)
-
π Fix
AssetFile
constraint violation during the asset file cleanup in rebuilds. This could prevent library rebuilds from completing successfully. -
π If an Apache reverse proxy closed the SSE socket, PhotoStructure would pop up a “π© Not connected” error. This build skips showing that error and tries to quietly restore the SSE socket when broken. See this forum post for details.
-
π PhotoStructure can now allow drives to go to sleep. It should “just work,” but to set
volumeMetadataTtlMs=0
andmountpointsTtlMs=0
to force this behavior on platforms that don’t have mountpoint-change-watcher functionality.mountpointsTtlMs
defaults to 0 on docker now, btw. -
π Fixed off-center home icon on Safari (the
displayPath
for the root tag was[ null ]
, oops) -
π Note: file picker dialogs on PhotoStructure for Desktops that use Linux Gnome can pop-under as a “feature” of Gnome. See https://github.com/electron/electron/issues/32857 for details.
-
β¨/π¦ System load is now exposed in the about page and the
info
tool. -
β¨/π¦ File I/O was reduced a bit–permission checks now directly use the
Stats
object if cached, rather than requiring a separateaccess()
I/O call. -
β¨/π¦ “Actual path” resolution on case-insensitive systems now ensure the correctly-cased pathname is used for URIs. Incorrect case could prevent cross-platform asset file correlation.
-
β¨/π¦ The new
fsCacheSlowMs
setting supports sharing work, like image hashing and metadata parsing and inference, between processes, which can avoid duplicating work during asset importing. -
β¨/π¦ The new
siblingInference
setting helps PhotoStructure work around (very) large directories. See the setting for details. -
π¦ PhotoStructure now requires at least Node.js v16, and is tested on 18 and 20.
-
π¦ System load on macOS and Linux now average together both proc/cpu metrics as well as loadavg(), which should help PhotoStructure throttle work more accurately.
-
π¦ Control SQLite’s synchronous mode via the new
dbSynchronousMode
setting. -
π¦ If file copies are problematic (you’d see
warn
log entries to this effect), you can now force PhotoStructure to usecp -af
(on macOS and Linux) orCopy-Item
(on Windows) by setting the newonlyNativeFileCopy
setting totrue
. -
π¦ Control PowerShell child process concurrency via the new
powerShellProcs
setting -
π¦ Added support for newer NEF and old KDC image formats
-
π¦ New setting
twoDigitCutoffYear
: sets the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century. As an example, a value of “50” would make “49” be interpreted as 1949, and “50” as 2050. See https://moment.github.io/luxon/api-docs/index.html#settingstwodigitcutoffyear for details. This defaults to 3 years in the future (modulus 100) and is updated automatically. -
π¦ Some string handling previously used now-deprecated
.substr()
. PhotoStructure now uses locale-aware grapheme splitting where available, which should prevent high-unicode text from being corrupted. -
π¦ Volume UUID files, .JSON files, and .TOML files all now support UTF-8, UTF-8-with-BOM, and UTF-16LE-with-BOM encodings, and are now normalized before
volsha()
‘ed (so{abc-012-789}
will be considered equivalent toabc012789
) -
π¦ Added 20 new serial-to-model-name translations for recently released smartphones and cameras
-
π¦ Pulled in latest versions of Electron, sharp, node, TypeScript, ExifTool, and other third-party libraries.
-
π¦ When spinning up the
photostructure/server
docker image, better error messages are now emitted when/ps/library
is missing. -
π¦ Mountpoint and volume extraction is now more configurable. See the new
excludedFilesystemTypes
,excludedRootDirectories
andexcludedMountpoints
settings.isExcludedMountpoint()
now debug-logs why a given mountpoint is excluded, to help tune these settings. -
π¦ Process
renice
-ing and management should be more efficient, as PhotoStructure now defaults to libuv and only resorts to external tooling on failure. -
π¦ Supported file extensions and mimetypes are now defined in a single dictionary to ensure they are kept in synchronization. Due to the prior design, several more obscure file extensions (like
.KDC
) weren’t handled properly. -
π¦ Removed
--progress
fromsync
(it wasn’t used, and was an unnecessary third-party dependency) -
π¦ Most URLs in text files and emitted to stdout were wrapped in angle brackets, but some apps would interpret the trailing
>
was part of the URL (looking at you, UnRaid terminal), which 404ed. All wrapped URLs are just plaintext, separated with whitespace. -
π¦ Replaced “open library” locks with critical section file mutexes. This should avoid “this library is already open on $host” startup errors while still preventing concurrent system access. This means the
--force-open
argument for many of the tools is now gone. -
π¦ Volume UUIDs are now customizable, and support multiple paths. See the new
volumeUuidFilePaths
Setting for details. -
π¦ Camera and lens UUIDs are whitespace-normalized before being hashed (as RAW and JPG variants can sometimes only differ in spaces (!!))
-
π¦ Added Make/Model support for 20+ new flagship cameras
-
π¦ Added
.Make
backfiller fromSoftware
andCreatorTool
tags (useful for scanners)