Skip to content

illixion/SpatialStash

Repository files navigation

Spatial Stash

A visionOS app for Apple Vision Pro that transforms your 2D images into immersive 3D spatial photos. Browse your media library from a Stash server, local files, or use the built-in demo mode.

Features

  • 2D to 3D Conversion - Uses Apple's RealityKit to convert standard images into spatial 3D photos viewable on Vision Pro, with automatic restoration of 3D state for previously converted images
  • Stash Server Integration - Connect to your Stash media server via GraphQL API to browse images and videos
  • Local Files - Browse images and videos from the app's Documents folder
  • Share Sheet Support - Receive images and videos from other apps via the system share sheet, with save-to-files option
  • Advanced Filtering - Filter by galleries, tags, ratings, performers and more with saved filter presets
  • Swipe Navigation - Swipe between images in the gallery with smooth transitions
  • Slideshow - Random image slideshow with Ken Burns animation, dynamic brightness, clock overlay, and visual adjustments. Launches in a dedicated viewer window with configurable display options
  • Rating & O-Count - View and edit image ratings and O-count directly from the viewer
  • Video Playback - Stream videos directly from your Stash server or play local files
  • Stereoscopic 3D Video - Automatically detects SBS/OU stereoscopic formats from tags, converts to MV-HEVC, and plays in full immersive mode
  • Pseudo 3D Video Conversion - Converts flat videos into windowed stereoscopic 3D using Core ML monocular depth (Depth Anything V2). Choose between real-time (instant, 30fps inference-bound) or pre-processed (background conversion for exact-frame 60fps playback with offline-optimized depth quality). Adjustable depth strength, convergence, and Subtle/Medium/Strong presets. Models downloaded on-demand from Apple's Hugging Face repo, switchable and deletable from the view-mode menu. With "Real-Time 3D for All Videos" enabled in Settings, eligible videos auto-engage 3D on open
  • Unlimited Windows - Open multiple image viewer windows that persist in your space
  • Memory Management - Lightweight 2D display by default with automatic downsampling, configurable dynamic image resolution, and memory-aware window management
  • Demo Mode - Try the app with bundled sample images without server setup

Screenshots

Home Viewer Filters Local Settings

Requirements

  • Apple Vision Pro or visionOS Simulator
  • Xcode 15.0+
  • visionOS 26.0+
  • (Optional) Stash server for media library integration

Installation

  1. Clone the repository:

    git clone https://github.com/illixion/spatialstash.git
    cd spatialstash
  2. Open the project in Xcode:

    open SpatialStash/SpatialStash.xcodeproj
  3. Select your development team in Xcode (Project → Signing & Capabilities)

  4. Build and run on visionOS Simulator or device (Cmd+R)

Configuration

Demo Mode

The app starts in demo mode with sample images. No configuration required.

Stash Server

To connect to your Stash server:

  1. Open the app and navigate to the Settings tab
  2. Change Media Source to "Stash Server"
  3. Enter your Stash server URL (e.g., http://192.168.1.100:9999)
  4. Enter your API key if authentication is enabled
  5. Tap Apply & Test Connection

Local Files

To use local files:

  1. Change Media Source to "Local Files"
  2. Place images in the app's Documents/Photos/ folder and videos in Documents/Videos/
  3. Tap Refresh All Content to scan for new files

Usage

Pictures Tab

Browse your image gallery in a grid view. Tap any image to open it in the viewer:

  • Swipe left/right to navigate between images
  • Tap the 2D/3D button to generate a spatial 3D version and toggle it on/off (3D generation may take a few seconds)
  • Tap the person outline button to toggle background removal
  • Tap the play button to launch a slideshow viewer with Ken Burns animation, clock overlay, and visual adjustment controls
  • Tap the star button to view/edit rating and O-count (Stash server only)
  • Tap the pop-out button to open the image in its own window
  • Images previously viewed in 3D show a "Restore 3D" prompt pill that opts you back in with one tap (auto-dismisses after 10s)
  • The window automatically adjusts to match image aspect ratios

Videos Tab

Browse and play videos. Tap the view-mode button in the ornament to switch between flat 2D, Pseudo 3D (2D→3D conversion), and (for tagged SBS/OU sources) full immersive Stereoscopic 3D:

Pseudo 3D Conversion

Converts any flat video into windowed stereoscopic 3D using Core ML monocular depth (Depth Anything V2):

  • Real-Time mode - Instant, 30fps
  • Pre-Processed mode - Background conversion for 60fps cached playback: downloads a low-res copy of your video, infers depth for every frame offline, applies advanced filtering and temporal smoothing, and caches the depth in a compact HEVC sidecar. You can watch the video in 2D while the conversion runs in the background, then switch to 3D playback once it's ready (or let it auto-engage mid-conversion). Future plays use the cached depth at full framerate with zero ANE load. Conversion time is ~0.5–1× realtime depending on video length and your system
    • The first time you access 3D conversion, a setup sheet lets you download a depth model on-demand — straight from Apple's Hugging Face repo, ~19–50 MB depending on the variant (Depth Anything V2 Small in F16, INT8, 6-bit, or 8-bit palettized; larger variants yield better depth quality)
    • Installed models can be switched, deleted, or supplemented with your own custom model via scripts/convert-depth-model.py
    • Both Depth Model (Real-Time) and Depth Model (Pre-Process) submenus appear in the view-mode menu, letting you pick the model for each pipeline without visiting Settings (real-time model changes apply to the playing video immediately; pre-process model applies to future conversions and cache lookups)
  • Pick Subtle/Medium/Strong depth presets from the menu, and fine-tune Stereo Separation, Convergence, and (in pre-process) Auto Convergence in the Adjustments window (which opens as its own repositionable window so it never sits behind the 3D video)
  • Settings → Display → "Real-Time 3D for All Videos" enables auto-engagement: eligible videos (native-Metal playable, not genuinely stereoscopic) open with Pseudo 3D already engaged — prefers the cached pre-process depth when available, otherwise uses real-time inference

Stereoscopic 3D

Videos automatically detected from Stash tags (SBS/Over-Under format) are converted to MV-HEVC and play in full immersive mode.

Playback

  • Custom control bar (play/pause, scrubber with buffered range, A-B loop, mute) for flat 2D videos
  • In Pseudo 3D mode, transport controls fold into the ornament so all chrome shares the video's depth plane
  • Full window aspect ratio locking ensures videos maintain their proper proportions

Filters Tab

Create complex queries to filter your media (Stash server only):

  • Search by title
  • Filter by galleries, performers, studios, tags
  • Filter by rating (1-5 stars) or O-count
  • Sort by date, title, rating, or random
  • Save filter combinations as presets for quick access or as default views

Settings Tab

  • Media Source - Switch between Demo, Stash Server, and Local Files
  • Dynamic Image Resolution - Toggle automatic image downsampling based on window size (on by default, turn off for full-resolution display)
  • Auto-hide Controls - Configure how long ornament controls stay visible
  • Slideshow Delay - Set the interval between slideshow images
  • Real-Time 3D Depth Model / Pre-Process 3D Depth Model - Select which installed monocular depth model each pipeline uses. Models are downloaded on-demand from Apple's Hugging Face repo (~19–50 MB each) and stored internally. Real-time model changes apply immediately to the playing video; pre-process model changes apply to future conversions. Switched or deleted via the view-mode menu or these Display settings
  • Real-Time 3D for All Videos - When enabled, eligible videos (native-Metal playable) auto-engage Pseudo 3D on open, using cached pre-processed depth when available or real-time inference otherwise
  • 3D Depth Model Manager (Developer) - Download, switch between, or delete the monocular depth models. Models are fetched directly from Apple's Hugging Face repo and stored internally; a custom model pushed to the app's Documents folder (via scripts/convert-depth-model.py) is imported automatically on launch
  • Converted 3D Videos (Developer) - Manage pre-processed depth caches: view size and conversion model per video, delete individual entries, or clear all
  • Cache Management - View and clear image/video disk caches
  • Stash Server - Configure server URL and API key

Remote API Viewer (Developer)

A slideshow viewer for displaying images from a RoboFrame proxy API, with WebSocket-based remote control and Home Assistant sensor integration. Enable in Settings → Developer → Enable Remote API Viewer.

  • Configurable API endpoint with saved configuration profiles
  • Tag list management with per-config tag lists and bulk update across all configs
  • Image prefetching for instant transitions (3 images buffered ahead)
  • Ken Burns effect with Sobel edge detection to zoom toward interesting regions
  • Dynamic brightness that auto-boosts dark images based on luminance analysis
  • Clock and sensor overlays with configurable text size and semi-opaque backgrounds
  • WebSocket RPC for remote display control, multi-device sync, and Home Assistant sensor data
  • Critical alertsplayVideo and showText WebSocket commands open new windows for home system notifications
  • Client-side content filtering with blocked post/tag lists (merged from server on connect)
  • Visual adjustments shared with the photo/video viewer system (brightness, contrast, saturation)

Architecture

The app follows a SwiftUI architecture with:

  • AppModel - Central @Observable state container for app-wide state
  • PhotoWindowModel - Per-window @Observable model for photo viewers, split into extensions by concern (visual adjustments, spatial 3D, background removal, memory management, gallery navigation, UI controls)
  • PhotoDisplayView + PhotoOrnamentView - Shared components used by all three photo viewer windows
  • Protocol-based data sources (ImageSource, VideoSource) for swappable implementations
  • StashAPIClient actor for thread-safe GraphQL communication
  • RealityKit integration via ImagePresentationComponent for spatial photos
  • StereoscopicVideoPlayer + MVHEVCConverter for stereoscopic 3D video conversion and immersive playback
  • Pseudo3DVideoPlayerView + StereoPump + CoreMLDepthProvider for real-time, windowed 2D→3D video conversion (per-eye Metal warp off the main thread)
  • DepthConverter + DepthCacheStore + DepthCacheReader for offline depth conversion pipeline: per-frame monocular depth inference with joint-bilateral luma-guided filtering, temporal lookahead smoothing, and compact HEVC depth sidecar + metadata storage
  • DepthConversionManager for background conversion job queue with progress tracking, progressive playback (auto-engage 3D mid-conversion when safe), and resumption after app backgrounding
  • Pseudo3DStereoEngine configurable for real-time or cached depth source, both at exact-frame PTS matching for zero ghosting

License

See LICENSE.txt for licensing information.

Acknowledgments

  • Stash - Self-hosted media organizer
  • Built with Apple's RealityKit and SwiftUI frameworks

About

visionOS Stash-compatible image and video viewer with 2D → 3D conversion support

Topics

Resources

License

Stars

5 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors

Languages