Your Jellyfin library and Seerr, together on every Apple screen.
Native for Apple TV, iPhone and iPad. Instant playback, real HDR, real Dolby Atmos.
Browse what you own. Request what's missing. Tune into live TV.
On the couch, in your hand, wherever you are.
π§ͺ Public Beta is open. One TestFlight link installs on Apple TV, iPhone and iPad: https://testflight.apple.com/join/nWeQzmBX See BETA.md for what to focus on and how to report bugs.
Sodalite is a single universal app. The same library, the same Seerr request loop, the same custom video stack, whether you're on the Apple TV in the living room, an iPhone on the train, or an iPad in bed. Sign in once per server; the whole experience follows the device you pick up.
It brings Jellyfin and Seerr together in the same UI. Watch what's already on your server. Spot something on a trending row that isn't there yet? Request it from inside the app, and Seerr handles the rest. No switching to a phone browser, no pinging your homelab admin, no leaving the app you're already in.
![]() |
![]() |
| Home (Apple TV) | Live TV (Apple TV) |
![]() |
![]() |
| Catalog (Apple TV) | Music (Apple TV) |
![]() |
![]() |
![]() |
![]() |
| Home (iPhone) | Detail (iPhone) | Home (iPad) | Catalog (iPad) |
Almost everything is identical across devices, it's one codebase. A handful of capabilities are platform-native by design:
| Capability | Apple TV | iPhone & iPad |
|---|---|---|
| Full library, Direct Play, HDR, Dolby Atmos, all subtitle formats | β | β |
| Seerr browse & request, single sign-on | β | β |
| Live TV & DVR | β | β |
| Music library | β | β |
| Watch Stats, parental controls, 26 languages | β | β |
| Picture in Picture | β | β |
| AirPlay to another display | β | β |
| Full-screen video out over a wired HDMI adapter | β | β |
| Rotation lock & portrait player | β | β |
| Child lock in the player | β | β |
| Top Shelf & Siri Remote focus UX | β | β |
Sodalite is open from end to end. Every byte that touches your server is in this repo, your credentials live in your device's Keychain and sync between your devices only through your private iCloud, end-to-end encrypted so not even Apple can read them (turn iCloud Sync off and they never leave the device), and there's no telemetry, no analytics, no third-party SDK phoning home.
Licensed under GPL-3.0 with an Apple Store / DRM Exception. Fork it, study it, build your own version, but no one can take it private. Modifications must stay open. The exception clause in the LICENSE keeps the App Store and TestFlight distribution paths legally clean. The video stack underneath (AetherEngine) is LGPL-3.0 with the same Apple Store exception, so the engine can be reused in other apps while engine-level improvements flow back to the community. Both are auditable, buildable from source, and free of any vendor lock-in. Self-host the server, self-build the client, the whole loop is yours.
Sodalite is built natively from the ground up: SwiftUI on top, a custom video engine underneath, and the same HIG patterns Apple uses across its own apps, focus engine and Siri Remote gestures on tvOS, touch and rotation on iPhone and iPad. It plays the file directly from your server in almost every case, no transcoding required, and live channels stream straight from their source where possible.
The Seerr integration isn't a tacked-on link to a web view. It's a first-class part of the app, with its own browse rows, request flow, and status tracking right next to your library.
- Server discovery: finds Jellyfin on your network automatically, or add manually
- Multiple servers: keep several Jellyfin servers in the app and switch between them without logging out; pick or add one from above your profile list, manage the full list in Settings β Servers
- Internal / external URLs: give a server both a local address and a remote one; Sodalite probes each and automatically switches to whichever one actually answers, rather than guessing from network type, so it keeps working over a VPN. Editable per server on iPhone and iPad, for both Jellyfin and Seerr, with a badge showing the active route; Apple TV resolves once when a session starts.
- Home: Continue Watching, Next Up, a separate Latest row for each of your libraries, plus a My Media row to jump straight into any library; every row can be toggled and reordered, and Continue Watching and Next Up can optionally merge into a single row
- Library: Movies, Series, Collections with poster grids, instant filtering and an All / Unwatched / Watched watch-status filter on every grid
- Series view: season picker, episode list, "Up Next" highlighting
- Playlists: your Jellyfin playlists get their own Home row and a detail page that plays through in order
- Search: across your whole server, results as you type
- Image caching & prefetching: posters and backdrops load before you reach them
- Delete from the app: remove movies, series, or individual seasons from your library, with optional cleanup of matching Radarr / Sonarr entries when Jellyseerr is connected
- Rich detail pages: cast, ratings, where-to-watch and more-like-this on catalog titles; tagline, director, writer and studios on your own library
- Title logos & synopses: detail screens float the title logo over the backdrop and show full episode synopses, both toggleable in Appearance settings
- Full-bleed backdrops: artwork shines through the whole detail page and dims as you scroll; titles without backdrop art get an ambient poster fill instead of a grey plate
- Watched tracking: mark movies, episodes, seasons or whole series as watched or unwatched, with progress badges across Home and detail screens
- Cast & filmography: open any cast member to see their photo, biography and full filmography, then jump straight to a title in your library or request it from the catalog
- Direct Play for almost every codec on your server: H.264, HEVC, HEVC Main10, AV1, VP9, VP8, MPEG-4 Part 2 (XVID / DIVX), MPEG-2, VC-1. Containers: MKV, MP4, MOV, AVI, MPEG-TS, M2TS, VOB, 3GP, WebM, OGG, FLV. Server-side transcoding stays reserved for fringe codecs (WMV3, Theora, RealVideo).
- HDR10, HDR10+, Dolby Vision, HLG: auto-detected, sent through with full color metadata. HDR10+ streams forward per-frame ST 2094-40 dynamic metadata so HDR10+ displays apply the source's tone-mapping curves; Dolby Vision streams switch DV-capable Apple TVs into Dolby Vision mode for Profile 5, 8.1 and 8.4 (Profile 7 is converted to single-layer 8.1 on device so it engages DV too): Profile 5 signals via a bare
dvh1track tag, while 8.1 and 8.4 carrydvh1inSUPPLEMENTAL-CODECSon anhvc1base. On Apple TV the display switches to the matching HDR mode automatically (Match Content); on iPhone and iPad the built-in HDR display renders it directly. - Dolby Atmos via EAC3+JOC, wrapped as Dolby MAT 2.0 so an AVR's Atmos light actually comes on over an Apple TV; on iPhone and iPad it plays through spatialized audio where the device supports it
- Multichannel surround: 5.1, 7.1 with correct channel layout
- Resume from where you left off, on any device
- Restart from the beginning: a dedicated button on movies, series and episodes to play from the start instead of resuming
- Pick your source: when a title has more than one version on your server (different rips, resolutions or editions), a picker lets you choose which one to play before playback starts, on both movies and episodes
- Shuffle a series: a shuffle button on series detail queues random episodes across every season
- Trailers: play a title's local trailer straight from your server with a dedicated button on the detail page
- Intro skip: auto-detected from your Jellyfin server, optional one-tap skip
- Next episode: auto-play with countdown, or just an overlay; configurable
- Subtitles, all formats, client-side: text codecs (SubRip, ASS, SSA, WebVTT, mov_text) decoded inline in AetherEngine as packets flow through the demuxer, no server extraction lag on first hit. Bitmap subtitles (PGS, HDMV PGS, DVB, DVD) rendered as native images at the right position on the frame, no more relying on the server having Tesseract installed for Blu-ray rips. Sidecar
.srt/.ass/.vttfiles parsed by FFmpeg as well. In-band CEA-608 closed captions (theeia_608caption track some streams and rips carry) are decoded on-device too and appear in the subtitle menu like any other track. DVB Teletext subtitle pages from broadcast and live TV are decoded on-device as well, with their original colors preserved. Styled ASS / SSA rendering keeps the original fonts, colors and positioning, for both embedded and external sidecar tracks (toggle between styled and plain text in Playback settings). Track switching mid-playback, with auto-resolution against your preferred audio / subtitle language. - Forced subtitles with subtitles off: forced captions (signs, translated foreign dialogue) still show while your subtitles are off, like a disc player would. A dedicated forced track matching the audio language is used when the release has one; otherwise the forced-flagged cues inside the full PGS / DVD track are rendered on their own. Fully automatic, the subtitle menu keeps showing "None".
- Subtitle search & download: when your server is missing the right track, search and download subtitles from inside the player. Files that match by content hash get a badge so you know they line up, and ones you added can be removed with a long press.
- Dual subtitles: show a second simultaneous subtitle track above the first, for example the original language plus a translation. Pick a secondary track from the Secondary section at the top of the subtitle menu (text tracks only).
- Audio track switcher: pick the language or surround mix you want, mid-playback
- Scrub preview: thumbnails of the exact frame as you scrub, floating above the playhead, generated on-device by AetherEngine straight from the video so they land on the precise frame and work even when your server has no trickplay images prepared. An optional setting lets you prefer your server's pre-generated trickplay images instead (decode-free, lighter on older devices), falling back to on-device when the server has none
- Custom player UI: a hand-built transport bar and info panel on top of our own video engine, matching the gestures and feel of Apple's own player without using the system player
- Picture in Picture: shrink playback into a floating window and keep browsing, or leave the app entirely. On Apple TV start it from a dedicated transport-bar button (video and Live TV); on iPhone and iPad it also engages automatically when you swipe home. On iPhone and iPad it also works for software-decoded titles (AV1 without hardware decode, VP9), with the window's own play/pause/skip controls driving the engine directly; tvOS cannot offer that yet because its AVKit never engages picture in picture for sample-buffer sources. Text subtitles render inside the PiP window on the native path and survive seeking in both directions
- Now Playing skip: the 10-second forward and backward buttons in the system Now Playing controls (Control Center on iPhone and iPad, the Now Playing panel on Apple TV) route through to the engine via
MPRemoteCommandCenter, App Store compliant, no private API - Stats for Nerds overlay: optional info panel during playback. Static section shows container, video codec / range / framerate / bitrate / decoder, audio codec / channels / bitrate / decoder, subtitle codec. Live section refreshes at 1 Hz with instant + average bitrate from the demuxer, forward buffer + cached MB, network throughput, dropped frames (native AVPlayer) or observed FPS (software AV1), plus a colour-coded A/V sync gap. A second toggle adds an Engine Diagnostics deep-dive (producer restarts, RSS, demuxer / muxer / audio-bridge bytes, server traffic) for troubleshooting. Enable in Settings β Playback β Advanced.
- AirPlay: send any title to an AirPlay display, with HDR and surround metadata preserved
- Wired HDMI out: plug in a USB-C to HDMI adapter and playback fills the connected screen instead of showing the mirrored phone window, with HDR / Dolby Vision and match-frame-rate passed through; subtitles render on the external screen too
- Rotation lock: a one-tap toggle in the player pins landscape (or lets it follow the device), with a lock indicator so you always know which mode you're in
- Child lock: one tap in the player disables every touch, so a child can watch without accidentally skipping, pausing, or leaving; release it by pressing and holding the on-screen pill for a moment
- Format badge: the top bar surfaces the live format (Dolby Vision, HDR10+, Atmos and friends) so you can confirm at a glance what's actually playing
- Portrait-safe chrome: player controls stay correctly placed in portrait and landscape, no clipped buttons behind the notch or home indicator
- Touch-native throughout: swipe to scrub, tap to play/pause, drag the grids, the whole app is built for touch as a first-class input, not a ported remote UI
- Overview tab: Live TV opens on a category-based overview of what's on right now, with rows mirroring the native Jellyfin guide, before you drop into the full grid
- Programme guide: full EPG grid with a sticky channel column, wall-clock time ruler, live now-line and current-program highlighting; open a program for info, watch and record actions
- Channel favorites: star channels in the guide, favorites sort to the top
- Timeshift: pause live TV, scrub back up to 10 minutes with on-device frame previews, snap back with Return to Live
- Recordings & timers: record a program or a whole series from the guide, manage scheduled timers, and play finished or still-recording shows
- Direct from the source: most channels play straight from their upstream, starting in seconds with no server transcoding, with automatic fallback through Jellyfin when a source needs it
- Same engine as movies: H.264 / HEVC channels ride the native pipeline, MPEG-2 / VC-1 and friends decode in software, and dead sources fail fast with a clear message instead of an endless spinner
- Broadcast picture: interlaced channels (1080i, 576i and the like) are hardware-deinterlaced on the fly for a clean progressive image, and DVB Teletext subtitle pages render in the subtitle menu with their broadcast colors intact
- Music library: browse your Jellyfin music by album and play it back through the same engine, with a native Now Playing screen, cover art, scrubbing and background playback
- Seerr integration: browse trending and popular media right inside the app
- One-tap requests for movies and full series
- Track status: see what's been approved, declined, or is already downloading
- Honest availability: cross-checks your Jellyfin library so a title (or single season) deleted in Radarr / Sonarr shows as gone, not a stale "available", and stays re-requestable
- Single sign-on: log in once, Sodalite handles your Seerr session
- Admin view: with Jellyseerr admin permissions, approve, decline, edit, or delete any user's request right from the All Requests tab
- iCloud Sync: servers, logins and settings sync automatically across every device signed into the same iCloud account, end-to-end encrypted so only your devices can read the secrets (tokens, passwords, Seerr sessions, your Guardian PIN); on by default, manage it from Settings β iCloud Sync with a live status, a manual "push this device's settings" action, and the option to delete your iCloud data entirely
- Parental controls: set a Guardian PIN to protect profiles and lock changes to settings, servers and profiles; a locked device returns to the profile picker on a cold start and gated actions ask for the PIN first, with recovery via your Jellyfin password
- Watch Stats: a Settings screen with your viewing totals, movies and episodes watched, completion rate, estimated hours, top genres, most-rewatched and recently-watched titles, all aggregated client-side from standard Jellyfin data
- 26 languages: German, English, Spanish, French, Italian, Japanese, Korean, Norwegian, Dutch, Polish, Portuguese (BR + PT), Russian, Swedish, Simplified + Traditional Chinese, Turkish, Ukrainian, Czech, Slovak, Croatian, Finnish, Greek, Hungarian, Romanian, Danish
- Dark, minimal design that puts the artwork first, on the big screen and in your hand
- Appearance options: choose how Continue Watching and Now Playing artwork looks (episode still, backdrop or series thumb), set card size, toggle title logos, plus an accent color with the Supporter Pack
- Liquid Glass UI accents on tvOS 26 and iOS 26
- Input-native everywhere: Siri Remote touch scrubbing, click for play/pause and swipe gestures on Apple TV; touch scrubbing and gestures on iPhone and iPad
Sodalite is a thin native shell over a custom video stack: Apple's frameworks plus a Swift package that handles the formats Apple's own player can't on its own. The same stack runs on tvOS, iOS and iPadOS.
| Component | Technology |
|---|---|
| UI | SwiftUI + UIKit interop where needed, one universal target for Apple TV, iPhone and iPad |
| Video engine | AetherEngine: FFmpeg demux, AVPlayer + VideoToolbox for HEVC / H.264 / HW-AV1, dav1d + libavcodec for AV1 / VP9 / VP8 / MPEG-4 Part 2 / MPEG-2 / VC-1 software fallback; live TV ingested directly from HLS upstreams with engine-side DVR |
| Display | AVPlayer + AVPlayerLayer for the native path; AVSampleBufferDisplayLayer + AVSampleBufferRenderSynchronizer for the software path |
| Audio | AVPlayer over local HLS-fMP4 for the native path (Atmos as MAT 2.0, EAC3 5.1 bridge by default for Opus / TrueHD / MLP / DTS / DTS-HD MA / MP2 / MP3 so surround works on every modern soundbar via the bitstream tunnel; optional lossless FLAC bridge for AVRs that accept multichannel LPCM over HDMI); AVSampleBufferAudioRenderer for the software path |
| Networking | URLSession against the Jellyfin REST API |
| Persistence | Keychain for credentials, no telemetry storage |
| Media server | Jellyfin |
For the full pipeline detail (HDR routing, Atmos passthrough, A/V sync, channel-layout tagging), see the AetherEngine README.
| Device | Min |
|---|---|
| Apple TV | 4K (any generation), tvOS 26 |
| iPhone | iOS 26 |
| iPad | iPadOS 26 |
| Jellyfin server | 10.9+ recommended |
| Seerr (optional) | 2.0+ |
A 1080p Apple TV HD will technically run the app, but Direct Play of 4K HDR content needs the 4K hardware. On iPhone and iPad the built-in display renders HDR directly, no external panel required.
git clone https://github.com/superuser404notfound/Sodalite.git
cd Sodalite
open Sodalite.xcodeprojPick the Sodalite-tvOS scheme for Apple TV, or Sodalite-iOS for iPhone and iPad, choose a matching destination, and run. AetherEngine is referenced as a remote Swift Package pinned by commit SHA in project.yml, so Xcode resolves and fetches it from GitHub automatically. No local clone is required to build Sodalite.
If you also want to work on the engine, clone it next to this repo and switch the package reference to your local copy in Xcode:
~/Dev/
βββ Sodalite/
βββ AetherEngine/
Xcode 26+ and Swift 6.0+ are required. The Xcode project is generated from project.yml with XcodeGen (brew install xcodegen); the generated Sodalite.xcodeproj is committed, so a plain checkout builds without extra tooling. If you change targets or build settings, edit project.yml and regenerate with Scripts/generate-project.sh.
For engine-level debugging without a device in the loop, AetherEngine ships a standalone macOS CLI (aetherctl probe / serve / validate <url>). See AetherEngine's CLI docs for usage.
The App Store marketing screenshots are generated from raw device shots by a small Node + Playwright pipeline in Tools/appstore-shots/ (real screenshots on a designed background, localized headlines in 26 languages). See its README.
- Public TestFlight beta
- Music library
- Live TV + DVR support
- iPhone / iPad universal app
- App Store release
- In-app library-update banner via Jellyfin's WebSocket, surfaces a quiet notification when Sonarr / Radarr ingests new content while Sodalite is open. No backend service, no APNs, same self-hosted data flow as everything else
Everything happens in the open. No Discord, no closed garden.
- Discussions: Q&A, ideas, show-and-tell
- Issues: bugs and concrete feature requests
If you're not sure which to use, start a Discussion. Bugs get moved to Issues. Both are public, indexed by search engines, and stay tied to the project, so the next person with the same question can find the answer.
Sodalite is free and stays that way. If it's useful to you and you'd like to say thanks, there's a Ko-fi. The app also has an in-app Tip Jar and a Supporter Pack (cosmetics only, no gating).
- AetherEngine: the video engine powering Sodalite
- Jellyfin: the free software media system
- Seerr: request management for Jellyfin
Sodalite is vibe-coded, designed and shipped by Vincent Herbst in close pair-programming with Claude (Anthropic). The commit log is the receipt: nearly every commit carries a Co-Authored-By: Claude trailer.
GPL-3.0 with Apple Store / DRM Exception. The exception clause keeps App Store and TestFlight distribution legally clean while the GPL keeps the source open and forks copyleft.








