Releases: epheterson/immich-apple-silicon
Releases · epheterson/immich-apple-silicon
Release list
Immich Accelerator v1.6.0
Added
- Native Swift ML engine, the new default (with automatic Python-venv fallback). The ML service (CLIP visual and text, face detection and recognition, OCR) can now run as a single native Swift binary instead of the ~1.5 GB Python venv (torch, mlx, onnxruntime, opencv, insightface) and the mlx-pin crash surface that came with it (#38, #103). CLIP runs on
mlx-swiftwith the same mlx-community weights; face embedding runs the identical InsightFace ArcFace model through onnxruntime's C API; detection and OCR use Apple's Vision framework. Same models and weights, so embeddings stay in the same space as an existing Immich index and face clusters: no re-index, no re-cluster. Validated against the Python service on real library photos (CLIP visual cosine ~0.996, CLIP text 1.0, face embedding ~0.999 bbox-matched, OCR identical). The native engine is preferred automatically; if its bundle or models are missing, or it fails to start or become healthy, the accelerator falls back to the Python venv so ML is never left down. On a fresh install the models (~740MB) download once in the background on first native start, so ML runs on the Python engine for a few minutes until they arrive. To switch back to the Python engine, set"ml_engine": "python"in~/.immich-accelerator/config.jsonand restart the accelerator (brew services restart epheterson/immich-accelerator/immich-accelerator); set it back to"native"or remove the key to return. Distributed as an ad-hoc-signed relocatable bundle over Homebrew, so there is no notarization step and no Gatekeeper friction.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require itImmich Accelerator v1.5.32
Fixed
- Install could silently ship a broken ML venv (#17, #105): the dashboard (
uvicorn) and the ML service (fastapi) both run out of one venv built in the formula'spost_install. If thatpip installpartially failed (typically a flaky connection on the largetorchdownload thatmlx_clippulls in), the venv existed but was missing packages, and nothing caught it, so the CLI reported the new version while the dashboard and ML crashed at runtime withModuleNotFoundError: No module named 'uvicorn'/'fastapi'. The formula now (1) retries the dependency install a couple of times so a transient network blip self-recovers, and (2) verifiesfastapi,uvicorn,mlx, and the dashboard app actually import after install, failing the install loudly (pointing atbrew reinstall immich-accelerator) instead of shipping a half-working setup. If you hit this on 1.5.31,brew reinstall immich-acceleratorrebuilds the venv. Reported by @jhoogeboom and @yz47.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require itCLIP ViT-B-32 model (native ML engine)
Version-independent model asset for the native Swift ML engine: CLIP ViT-B-32 safetensors + tokenizer (merges.txt, vocab.json), same weights as the Python mlx_clip path so embeddings stay compatible with an existing Immich index. Fetched once into ~/.cache/immich-ml-native/clip by the Homebrew formula. MIT (OpenAI CLIP).
Immich Accelerator v1.5.31
Fixed
- Reverted the mlx pin lift: mlx 0.32.0 also crashes CLIP (#103). v1.5.29 lifted
mlx>=0.22.0,<0.31.2to allow 0.32.0 after a re-test that only exercisedmlx_clip.image_encoderdirectly. That was insufficient: the real ML service/predictpath hard-crashes under 0.32.0 withstd::runtime_error: There is no Stream(cpu, 1) in current thread(the CPU-stream analogue of 0.31.2's #38 gpu-stream crash), on multiple Macs. The pin is back tomlx>=0.22.0,<0.31.2(resolves to 0.31.1, the last known-good). Runbrew upgrade immich-accelerator; if you were on 1.5.29/1.5.30 with ML failing, this restores it. Reported by @shtefko.
Added
scripts/ml-preflight.py— a real-model gate for mlx/ML changes. It boots the actual ML service withSTUB_MODE=falseand hammers/predictwith concurrent real CLIP inference, detecting the SIGABRT that aSTUB_MODEtest or animage_encoder-only loop misses. Verified it fails on mlx 0.32.0 (captures theStream(cpu, 1)abort) and passes on 0.31.1. The mlx pin and themlsubmodule are now gated on this on Apple Silicon (see CLAUDE.md), and the weekly mlx-pin check points re-tests at it. This is the gap that let the v1.5.29 regression ship.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require itImmich Accelerator v1.5.30
Fixed
- Camera RAW thumbnails failed (#99): Canon CR2 (and other camera RAW such as Nikon NEF, Sony ARW, Adobe DNG, Fujifilm RAF) died in
AssetGenerateThumbnailswithtiff2vips: Old-style JPEG compression support is not configured. Sharp's prebuilt libvips on macOS lacks old-style-JPEG support and has no dcraw/libraw loader, so it cannot read a RAW file's embedded image. The HEIC decode shim now also detects RAW by extension and pre-decodes it via Homebrewvips(fuller libtiff/libjpeg for TIFF-based RAW like CR2/NEF/ARW/DNG, plus libraw for the rest), the same libvips Docker Immich uses, before handing the result to Sharp. Works headless; OCR and face are untouched (RAW decode affects thumbnail generation only). Verified on an M4 Mac Mini with a real Canon CR2: bundled Sharp alone fails with the tiff2vips error, and with the shim it produces a valid thumbnail. Closes another macOS-only decode gap after the HEIC fix (v1.5.28). Reported by @shtefko. - Headless HEIC decode was silently falling back to
sips: Sharp's prebuilt libvips exports a bogusVIPSHOME(the GitHub-runner path it was built in, e.g./Users/runner/work/sharp-libvips/...) into the process environment when it loads. The decode shim spawned the Homebrewvipswith that inheritedVIPSHOME, sovipslooked for its loader modules (libheif for HEIC, the RAW loaders) in a nonexistent directory and failed withVipsForeignLoad: ... is not a known file format, falling back to Apple'ssips. Becausesipsneeds a logged-in GUI session, on a headless Mac the primaryvipspath (the entire point of the v1.5.28 HEIC fix) never actually ran, so HEIC thumbnails quietly depended on a desktop session. The shim now drops aVIPSHOMEthat points at a nonexistent directory before spawning a decoder, sovipsuses its own compiled-in module path and decodes HEIC and RAW headless as intended; an intentional, existingVIPSHOMEis preserved. Surfaced while adding RAW support and verified on a headless M4 Mac Mini (HEIC now decodes viavips, notsips).
Performance
- The
vipsdecode intermediate is now written as a lossless deflate-compressed TIFF (roughly 40% smaller than uncompressed) to trim peak memory and temp I/O when decoding large RAW frames. Pixels are unchanged; Sharp reads the deflate TIFF the same way.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require itImmich Accelerator v1.5.29
Changed
- Lifted the mlx pin now that 0.31.2's CLIP crash is fixed (#38): the bundled
immich-ml-metalfork pinnedmlx>=0.22.0,<0.31.2because mlx 0.31.2 hard-crashed CLIP inference in the worker's thread pool (std::runtime_error: There is no Stream(gpu, 0) in current thread, SIGABRT). mlx 0.32.0 is verified to fix it: 1,800 concurrent CLIP inferences from a 4/8-workerThreadPoolExecutoragainst realclip-vit-base-patch32weights on Apple Silicon, zero aborts. The pin is nowmlx>=0.22.0,!=0.31.2,<0.33.0, which excludes only the known-bad 0.31.2, allows the verified 0.32.x (currently the sole in-range build), and caps below the untested 0.33 minor. The weekly mlx-pin check now tracks that 0.33.0 ceiling instead of 0.31.2, so it stops nagging about 0.32.0. Blast radius is CLIP only: OCR runs on Apple Vision, face on onnxruntime, neither imports mlx.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require itImmich Accelerator v1.5.28
Fixed
- HEIC thumbnails failed on headless Macs (
Input file contains unsupported image formatonAssetGenerateThumbnails): the HEIC decode shim transcoded via Apple'ssips, butsipsneeds a logged-in GUI (Aqua/WindowServer) session, so in a headless launchd service it silently produced empty output and no HEIC thumbnail was generated. The shim now decodes via libheif (vips, already a dependency, thenheif-convert) as the primary path, which works with no GUI session and matches Docker Immich's own libvips+libde265 output;sipsremains a last-resort fallback for a logged-in desktop. Each decoder's output is validated before use, and the shim logs which decoders it resolved at startup.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require itImmich Accelerator v1.5.27
Fixed
- Immich 3.0 core plugin failed to import (
Failed to import plugin from /build/plugins/immich-plugin-core): the v1.5.24 layer-download early-exit treatedplugins/<name>/dist/plugin.wasmas "plugin complete", but 3.0 ships the plugin'smanifest.json(at the plugin root) in a separate image layer. Extraction stopped after the wasm layer and dropped the manifest, so the worker could not import the plugin and workflow features were unavailable. The fix has two parts:_build_has_core_pluginnow requires BOTH the manifest and the wasm before the early-exit fires; and the cached-server check now verifies the plugin actually belongs to the version being served before trusting the cache, so a broken 3.0 install self-heals on the next start after upgrading. Becausebuild-datais a single shared directory that only reflects the last-extracted version, that check is keyed on a version stamp written tobuild-dataonce it is complete, which avoids both trusting a stale cross-version plugin and needlessly re-downloading a cache that is fine. Existing installs (whose completebuild-datapredates the stamp) and offline--import-serverusers are adopted in place rather than re-downloaded, by matching the plugin against the requested version's layout, so upgrading is free. Applies to the ghcr download, local-Docker extraction, and offline import paths. Found by dogfooding 3.0.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require itImmich Accelerator v1.5.26
Fixed
- Motion-photo / video metadata errors on Immich 3.0 (#95):
probePacketsfailed withTypeError: Cannot read properties of undefined (reading 'split'). The pg_dump shim wrapschild_process.execFilebut dropped itsutil.promisify.customsymbol, so Immich 3.0'sconst execFile = promisify(execFileCb)fell back to the default promisifier and resolved to a bare stdout string instead of{ stdout, stderr }; destructuring{ stdout }then yieldedundefined. The shim now reinstalls a custom promisifier sopromisify(execFile)keeps the{ stdout, stderr }contract. A 3.0-only codepath, latent until now. Reported by @shtefko.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require itImmich Accelerator v1.5.25
Fixed
- Worker crash from file-descriptor exhaustion (#89): Immich leaks file handles while processing some media (a reporter hit it on Sony A7IV XAVC files on an external drive), opening each source file and never closing it. His diagnostic (from v1.5.23) showed ~49,000 open descriptors, all pointing at the source files; once the fd table is that large macOS fails
spawn()withEBADFand the worker crashes. The watcher now monitors the worker's live open-fd count (summed across worker processes, via libproc) and restarts the worker before the table gets dangerous (default 10,000; a healthy worker sits around 150), with a cooldown to avoid thrash. Tunable viaIMMICH_ACCEL_FD_RESTART_THRESHOLD(0 disables) andIMMICH_ACCEL_FD_RESTART_COOLDOWN. This is a safety net for an upstream Immich leak, not a fix for the leak itself.
Upgrade
brew upgrade immich-accelerator
immich-accelerator setup # if first time or new features require it