Skip to content

Releases: epheterson/immich-apple-silicon

Immich Accelerator v1.6.0

Choose a tag to compare

@github-actions github-actions released this 17 Jul 07:25
c62419c

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-swift with 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.json and 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 it

Immich Accelerator v1.5.32

Choose a tag to compare

@github-actions github-actions released this 16 Jul 15:21
b9611ba

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's post_install. If that pip install partially failed (typically a flaky connection on the large torch download that mlx_clip pulls 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 with ModuleNotFoundError: 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) verifies fastapi, uvicorn, mlx, and the dashboard app actually import after install, failing the install loudly (pointing at brew reinstall immich-accelerator) instead of shipping a half-working setup. If you hit this on 1.5.31, brew reinstall immich-accelerator rebuilds the venv. Reported by @jhoogeboom and @yz47.

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it

CLIP ViT-B-32 model (native ML engine)

Choose a tag to compare

@epheterson epheterson released this 17 Jul 06:33
b9611ba

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

Choose a tag to compare

@github-actions github-actions released this 15 Jul 16:20
553dc7d

Fixed

  • Reverted the mlx pin lift: mlx 0.32.0 also crashes CLIP (#103). v1.5.29 lifted mlx>=0.22.0,<0.31.2 to allow 0.32.0 after a re-test that only exercised mlx_clip.image_encoder directly. That was insufficient: the real ML service /predict path hard-crashes under 0.32.0 with std::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 to mlx>=0.22.0,<0.31.2 (resolves to 0.31.1, the last known-good). Run brew 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 with STUB_MODE=false and hammers /predict with concurrent real CLIP inference, detecting the SIGABRT that a STUB_MODE test or an image_encoder-only loop misses. Verified it fails on mlx 0.32.0 (captures the Stream(cpu, 1) abort) and passes on 0.31.1. The mlx pin and the ml submodule 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 it

Immich Accelerator v1.5.30

Choose a tag to compare

@github-actions github-actions released this 15 Jul 07:41
ad588a4

Fixed

  • Camera RAW thumbnails failed (#99): Canon CR2 (and other camera RAW such as Nikon NEF, Sony ARW, Adobe DNG, Fujifilm RAF) died in AssetGenerateThumbnails with tiff2vips: 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 Homebrew vips (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 bogus VIPSHOME (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 Homebrew vips with that inherited VIPSHOME, so vips looked for its loader modules (libheif for HEIC, the RAW loaders) in a nonexistent directory and failed with VipsForeignLoad: ... is not a known file format, falling back to Apple's sips. Because sips needs a logged-in GUI session, on a headless Mac the primary vips path (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 a VIPSHOME that points at a nonexistent directory before spawning a decoder, so vips uses its own compiled-in module path and decodes HEIC and RAW headless as intended; an intentional, existing VIPSHOME is preserved. Surfaced while adding RAW support and verified on a headless M4 Mac Mini (HEIC now decodes via vips, not sips).

Performance

  • The vips decode 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 it

Immich Accelerator v1.5.29

Choose a tag to compare

@github-actions github-actions released this 14 Jul 16:32
7fcc882

Changed

  • Lifted the mlx pin now that 0.31.2's CLIP crash is fixed (#38): the bundled immich-ml-metal fork pinned mlx>=0.22.0,<0.31.2 because 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-worker ThreadPoolExecutor against real clip-vit-base-patch32 weights on Apple Silicon, zero aborts. The pin is now mlx>=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 it

Immich Accelerator v1.5.28

Choose a tag to compare

@github-actions github-actions released this 12 Jul 13:47
11edbde

Fixed

  • HEIC thumbnails failed on headless Macs (Input file contains unsupported image format on AssetGenerateThumbnails): the HEIC decode shim transcoded via Apple's sips, but sips needs 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, then heif-convert) as the primary path, which works with no GUI session and matches Docker Immich's own libvips+libde265 output; sips remains 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 it

Immich Accelerator v1.5.27

Choose a tag to compare

@github-actions github-actions released this 10 Jul 07:28
79c77bd

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 treated plugins/<name>/dist/plugin.wasm as "plugin complete", but 3.0 ships the plugin's manifest.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_plugin now 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. Because build-data is a single shared directory that only reflects the last-extracted version, that check is keyed on a version stamp written to build-data once it is complete, which avoids both trusting a stale cross-version plugin and needlessly re-downloading a cache that is fine. Existing installs (whose complete build-data predates the stamp) and offline --import-server users 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 it

Immich Accelerator v1.5.26

Choose a tag to compare

@github-actions github-actions released this 09 Jul 18:09
ccc8951

Fixed

  • Motion-photo / video metadata errors on Immich 3.0 (#95): probePackets failed with TypeError: Cannot read properties of undefined (reading 'split'). The pg_dump shim wraps child_process.execFile but dropped its util.promisify.custom symbol, so Immich 3.0's const execFile = promisify(execFileCb) fell back to the default promisifier and resolved to a bare stdout string instead of { stdout, stderr }; destructuring { stdout } then yielded undefined. The shim now reinstalls a custom promisifier so promisify(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 it

Immich Accelerator v1.5.25

Choose a tag to compare

@github-actions github-actions released this 05 Jul 22:45
84bd516

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() with EBADF and 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 via IMMICH_ACCEL_FD_RESTART_THRESHOLD (0 disables) and IMMICH_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