Restyle the README: centered hero header, a screenshot row (timeline, Places map, server/backup), and an emoji feature list. Refresh the feature set and controls for what shipped since (smart search, the Places map + cluster gallery, analog-stick map control) and link the releases page. Screenshots live in docs/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011uKJQMYDE9Nrq9ECsU3MxH
5.7 KiB
📷 vitaImmich
Your self-hosted photo library, in your hands.
A native Immich client for the PlayStation Vita — browse, search and map your whole photo & video library over Wi‑Fi, play videos on the Vita's hardware decoder, and back up the camera roll, all on a 12‑year‑old handheld.
![]() |
![]() |
![]() |
| Timeline & search | Places map | Server & backup |
✨ Features
- 🗓️ Timeline — your entire library as a justified, date‑grouped grid (newest first), styled after the Immich web app.
- 🔍 Smart search — free‑text CLIP search straight from the Vita's keyboard.
- 🗺️ Places map — geotagged photos clustered on a world map; pan/zoom with the sticks and open any cluster as its own gallery.
- 🖼️ Full‑screen viewer — pinch/stick zoom & pan, swipe between photos, hardware‑accelerated H.264 video playback.
- ☁️ Camera‑roll backup — scans the Vita's photos & videos, dedupes against the server, and uploads on request.
- 📊 Server overview — storage usage, server/app versions, and per‑device backup status.
- 👆 Touch + buttons — the whole UI is drivable with the front touchscreen or the d‑pad/sticks.
Status: proof‑of‑concept. App title id
VIMM00001. See limitations.
📦 Requirements
- A PS Vita running HENkaku/h‑encore with VitaShell.
- A reasonably recent Immich server reachable over the Vita's Wi‑Fi.
- An Immich API key (web UI → Account Settings → API Keys), or an email/password.
🚀 Install & configure
-
Grab
vitaImmich.vpkfrom the latest release (or build it — see below) and install it with VitaShell. -
Launch it once; it creates
ux0:data/vitaimmich/config.txt. -
Edit that file (VitaShell's FTP, SELECT, makes this easy):
server=http://192.168.1.100:2283 apikey=your-immich-api-keyBehind a reverse proxy without NAT loopback? Pin the domain to your LAN IP so the Host header / TLS SNI stay on the domain but the connection goes straight to the server:
server=https://immich.example.com apikey=your-immich-api-key serverip=192.168.1.100 -
Relaunch.
🎮 Controls
Timeline
| Button | Action |
|---|---|
| D‑pad / sticks | Move selection (hold to repeat) |
| L / R | Jump a month up / down |
| △ | Smart search |
| X | Open full screen |
| 🗺️ / ☁️ (touch) | Open the Places map / server page |
| SELECT | Sync overview |
| START | Exit |
Places map
| Button | Action |
|---|---|
| Left stick / d‑pad / drag | Pan |
| Right stick / L · R | Zoom out / in |
| X | Open the centred cluster as a gallery |
| △ | Toggle the lat/lon graticule |
| O | Back |
Full‑screen viewer
| Button | Action |
|---|---|
| ← / → | Previous / next |
| Right stick / L · R | Zoom · left stick pans |
| X | Play video / retry a failed load |
| O | Back |
Video playback — X pause/resume · ←/→ seek ±10 s · O stop.
🔧 Building
Needs VitaSDK with libvita2d, curl, openssl,
zstd, zlib, libpng, libjpeg-turbo and freetype (install via vdpm).
export VITASDK=$HOME/vitasdk
export PATH=$VITASDK/bin:$PATH
cmake -B build -S .
cmake --build build # -> build/vitaImmich.vpk
The sources in src/ are a unity build: main.c #includes the section
files (state.c, draw.c, … app.c) into one translation unit, so only
main.c is compiled. The geotag map's base tiles live in assets/maptiles.pak,
generated from a world‑map image by tools/png_to_tiles.py.
☁️ Camera‑roll backup
On startup the app mounts the Photos app's storage (photo0: /
ux0:picture) plus ux0:video/CAMERA, scans for .jpg/.jpeg/.png/.mp4, and
merges those files into the same date‑sorted timeline as your server library. A
badge in each cell's corner shows status:
- 🔵 blue‑grey dot — cloud only
- 🔶 orange up‑arrow — local only
- 🟠 blinking — queued / uploading
- 🟢 green check — backed up (on both; shown once, as the server asset)
- 🔴 red dot — failed
A background thread SHA‑1‑hashes each local file and asks the server which
already exist (bulk-upload-check). Uploads never start on their own — open the
sync overview (SELECT) and press X to queue every local‑only file.
Tunables in config.txt: syncdir=<folder> (repeatable) and syncmaxmb=<MB>
(size cap; files over 512 MB are skipped by default, 0 disables).
⚠️ Limitations
- TLS verification is disabled (no CA bundle ships) — prefer plain HTTP on a trusted LAN, or treat HTTPS as unverified.
- Videos download in full to the memory card before playing (deleted after).
Playback is the Vita's hardware decoder via SceAvPlayer, so only MP4
(H.264/AAC) plays — Immich's transcoded
video/playbackstream is used. - Backup is one‑way (Vita → server);
deviceIdis hard‑coded to "PS Vita" and uploads aren't added to an album. - Thumbnails stream in one at a time on a background thread (grey placeholder until loaded); hashing the camera roll fills statuses in gradually.


