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 too 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.π
syncschedules a cleanup process after every 50 processed files. Unfortunately, this cleanup process would force-rebuild theTag.assetCountcolumn 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
WorkQueuejob 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.sherror iftimeoutwas 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
maxBusyDbMssetting for details.π¦ On Windows we now add
%ProgramData%\chocolatey\binas a backfill%PATH%entry (to help findffmpeg.exe). Thanks for reporting, @Leaky!π¦ Prior builds relied on the
ffmpegPathsetting to be resolvable. We now use thepathTo()function (which includes backfill default paths) for allffmpegcommandsπ¦ Added the current userid/groupid to the library directory health check message to simplify finding the correct PUID/PGID values.
π¦ Added
toolsDir,osToolsDir,ffmpeg, andsqlitepaths tophotostructure infoto aid in future debuggingπ¦ Added
jpegtranhealth check. You know you all wanted it.π¦
WorkQueuejob 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
IOWAITstalls 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!π¦
:alphadocker builds now overwrite:prealphabuildsπ¦ 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
tagAlbumTitleHierarchieshas 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 inherited by subsequent metadata extraction runs, and could cause
syncerrors (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
.Orientationas well as.Rotationfor 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
sidecarTagBlocklistis["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
DateTimeUTCandGPSDateTimetocapturedAtTagsFallbackπ¦ ExifTool upgraded to v12.70. π Thanks for 20 years of updates, Phil Harvey! π
π Privacy improvements
π¦ Added alias for
PS_OPT_OUTenvironment 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, andreportErrorssettings now default tofalsein code, but default totrueon 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, andautoUpdateCheckvalues 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
ffmpegScaleTypesetting has been deleted. FFmpeg reliably applies the “old-style”-s WxHresize setting reliably, and some versions don’t accept the “new-style”-vf scaleformat, 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
webservice can’t bind to the web port, themainservice now properly shuts down and relays the error to the terminal. Prior builds would retry spawningwebindefinitely, 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
validationErrorAllowlistwas 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
eschandling after hide/exclude/trash. Thanks for the bug report, Leon!π/π The
retainFileBirthtimessetting was removed, as theutimesnative 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.shnow runsgit pullwith 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-checknow 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
dbBackupRetentionCountandsyncReportRetentionCountsettings for details.π¦ Tool versions on Linux distributions that use
pacman(like Fedora and Arch) are now provided bypacman -Qo.π¦ Added
--timingto all tooling, which emits performance metrics collected during a run to stdout on exitπ¦ Added
--tagsto thelisttool 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
tagAlbumTitlesetting 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
excludeGlobsInLibrarysetting (introduced last build) was confusing, and has been deleted.The
disableIgnorableFilterssetting was renamed toomitDefaultExcludeGlobs, but does the same thing: if set totrue, users start with an empty set of exclusion globs, and useexcludeGlobsAddto 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)
β¨
ffmpegHwaccelcan 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-hwaccelargument.π
Asset.durationMsis 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.shwarnings and errors related to pythondisttoolsandsetuptoolsπ 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-checkis 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
checkBasenameMatchessetting (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 /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 x64orUbuntu 22.04.3 LTS on x64) - Your current subscription (
PLUSorLITE)
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, orBy setting
PS_ALLOW_USER_AGENT=false, which makes theUser-Agentbe simplyPhotoStructure, orBy 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_CHECKto false - the default value of
PS_ALLOW_USER_AGENTto false, and - the default value of
PS_REPORT_ERRORSto 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
-fastargument 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).ffmpegtranscode rescaling could fail on older versions, causing videos to not be imported. We now try the new-style-filter:v scale=WIDTH:HEIGHTformat, and automatically downgrade to the older style-s WIDTHxHEIGHTargument format if there are errors. See the newffmpegScaleTypesetting for details:π
ffmpegtranscoding now supports bounded framerates. See the newtranscodeFrameRatesetting 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.
π
syncre-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_MBwill 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
validateMimetypeSkiplistsetting, and addingJpgFromRaw2to the default set of theembeddedPreviewssetting.π PhotoStructure tried to look at Linux
cgroupfiles 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
assetPathnameFormatsetting 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_LEVELnow defaults to the value ofPS_LOG_LEVELif unset.π¦ Added version extraction backstop for Debian/Ubuntu external tooling (mostly for
heif-convertdebugging).π¦ PhotoStructure can now use
dpkg -Sto check for installed versions of tools on Debian-based systems (which will help debug issues withffmpegandheif-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.
π¦
extraDateTimeFormatsnow 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
ffmpegandheif-convert(if version metadata is available).π¦
backfillTimezonesandinferTimezoneFromDatestampsare now exposed by settings and enabled by default. See the documentation for details.π¦ ExifTool
MWGmode is now enabled by default. See the newuseMWGsetting to revert to prior behavior. See https://exiftool.org/TagNames/MWG.html for details.π¦ On Windows,
%SystemDrive%\cygwin64\binis now checked for external tooling even if it’s not in the%PATH%π¦ Improved make/model handling for several new flagship mirrorless cameras
π¦
infoimprovements:- 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
excludeGlobsInLibrarysetting 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
undefinedfor 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
SubSecdatetime fields could assume the current date (!!). This is now fixed.π The CPU busy code was incorrectly filtering all values (!!), which led to the
undefinedcpu percent in the health checkπ¦ Adjusted
maxCpus()to account forsyncload to more accurately schedule the correct number of import jobsπ¦
SystemLoadHealthChecknow refreshes every minuteπ¦ Current system load was added to the
/aboutpageπ¦ 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.sharesare 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
ffmpegoverscheduling by moving the--threadsargument after the input. The default value for--threadsremainsclamp(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.
π
syncwill 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:2023didn’t work (thanks for the report and assistance, @avdp and @tkohhh)π When rotating images with prior versions,
-Orientationwould always be delivered to sidecars (because thePS_SIDECAR_TAG_BLOCKLISTincludedOrientation, but we have to pass-Orientation#to ExifTool). Unfortunately, nothing respects sidecarOrientationvalues, 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
DateandDateTimewere 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
Orientationtag 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
webnow 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
giowasn’t installed. This was fixed.π
syncis now properly restarted when settings are saved, which should fix “initial scan not starting on it’s own”–thanks for the report, @advp!π¦ Dropped
fsCachefor 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.
π¦
Errorstacktraces are included in log metadata, which may help expedite issue reproduction.
v2023.8.0-prealpha.12
Released 2023 August 28
- π¦ Skip
lsblkon 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_PATHSsetting 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.shby directlyexecingphotostructure.jsrather than using/usr/local/bin/nodeπ Fix spurious “No eligible files found in scanned paths”
π¦ Install
source-map-supportfor 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
allowFuzzyDateImageHashMatchessetting. 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 defaultingmaxConcurrentImportsto 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.
π
syncmemory 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, andsyncis 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
ffmpegpackage 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
.warnand.infologs
v23.8.0-prealpha.2-5
Released 2023 August 9
π Support
$PUIDand$PGIDvalues of 1000 (which collides with the docker imagenodeuser and group) (details)π Upgrade Dockerfile to Node.js v20
π Disable
proc-not-superuserhealth check on Windows by default: everyone always runs as an admin user.π Fix github actions to properly tag
:prealphabuilds
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.MICRO. Note that we are not using YYYY.0M.MICRO, or zero-padded months, as that violates Semantic Versioning and breaks some tooling (cough npm cough).
β¨ PhotoStructure no longer “fails fast.”
PhotoStructure will try to stay up and running, even if your library isn’t available or something’s amiss (like a misconfiguration or system issue).
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.

PhotoStructure’s new health check page
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
-walwrite-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
Viewmenu 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/appto/opt/photostructure. This move shouldn’t impact anyone, and was made to avoid people being confused by mounting anything to/psand 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, anddominantColorGreyThresholdsettings.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 better 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
CreateDatetag 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 thecapturedAtTagsand newcapturedAtTagsFallbacksettings. 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
minCapturedAtPrecisionandfuzzyDatePrecisionCoefffor 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 and 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
assetAggregationsetting tounionto 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
ffmpegpackage 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
transcodeMaxResolutionsetting 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
EBUSYorENOENTerrors 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,
validationErrorBlocklistandvalidationErrorAllowlist, now handle more corruption patterns.
π/π The
processPrioritysetting no longer supportsAboveNormal. If your settings used this value,processPrioritywill resort to the default,Idle.AboveNormalonly worked if PhotoStructure was running as root (which it never should do!)β¨/π¦ The
/site.webmanifestfile is now dynamically generated, and includes a properstart_url(so every launch will pick a new seed) and defaults todisplay: fullscreen.β¨/π¦
infotool improvements:Image hash comparison information, including all correlations, deltas, and thresholds, are now included for files (which may help tune
imageHash*Deltasettings values).Dominiant colors now include friendly names and percent image coverage.
Limit output to only image hash metadata with the new
--image-hashfilter.pathToLibraryAssetis now rendered for every file to help debug theassetPathnameFormatsetting.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
infoto 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.tomland.psenvfiles 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-convertthat 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-convertuntil restart, which caused confusion for some users. PhotoStructure will now detect newly-installedheif-convertbinaries within a minute.π Fixed docker
:alpha,:beta, and:stabletagging (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$PATHlooking for binaries withrxaccess. If$PATHis somehow truncated or invalid, we also walk some default paths (like%SYSTEMROOT%on Windows, and/usr/binand/usr/local/binon macOS and Linux).This fixes
sqlite.exe not foundandjpegtran.exe not founderrors 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
AssetFileconstraint 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=0andmountpointsTtlMs=0to force this behavior on platforms that don’t have mountpoint-change-watcher functionality.mountpointsTtlMsdefaults to 0 on docker now, btw.π Fixed off-center home icon on Safari (the
displayPathfor 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
infotool.β¨/π¦ File I/O was reduced a bit–permission checks now directly use the
Statsobject 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
fsCacheSlowMssetting supports sharing work, like image hashing and metadata parsing and inference, between processes, which can avoid duplicating work during asset importing.β¨/π¦ The new
siblingInferencesetting 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
dbSynchronousModesetting.π¦ If file copies are problematic (you’d see
warnlog entries to this effect), you can now force PhotoStructure to usecp -af(on macOS and Linux) orCopy-Item(on Windows) by setting the newonlyNativeFileCopysetting totrue.π¦ Control PowerShell child process concurrency via the new
powerShellProcssettingπ¦ 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/serverdocker image, better error messages are now emitted when/ps/libraryis missing.π¦ Mountpoint and volume extraction is now more configurable. See the new
excludedFilesystemTypes,excludedRootDirectoriesandexcludedMountpointssettings.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
--progressfromsync(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-openargument for many of the tools is now gone.π¦ Volume UUIDs are now customizable, and support multiple paths. See the new
volumeUuidFilePathsSetting 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
.Makebackfiller fromSoftwareandCreatorTooltags (useful for scanners)
