# JellyTau A cross-platform Jellyfin client built with Tauri, SvelteKit, and TypeScript. ## Recommended IDE Setup [VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer). --- # Requirements Specification ## 1. User Requirements | ID | Requirement | Priority | Status | |----|-------------|----------|--------| | UR-001 | Run the app on multiple platforms (Linux, Android) | High | In Progress | | UR-002 | Access media when online or offline | High | Done | | UR-003 | Play videos | High | Planned | | UR-004 | Play audio uninterrupted | High | Planned | | UR-005 | Control media playback (pause, play, skip, scrub) | High | In Progress | | UR-006 | Control media when device is on lock screen or via BLE headsets | Medium | Planned | | UR-007 | Navigate media in library | High | Done | | UR-008 | Search media across libraries | High | Done | | UR-009 | Connect to Jellyfin to access media | High | Done | | UR-010 | Control playback of Jellyfin remote sessions | Low | Planned | | UR-011 | Download media on demand | Medium | Done | | UR-012 | Login info shall be stored securely and persistently | High | Done | | UR-013 | View and manage downloaded media | Medium | Done | | UR-014 | Make and edit playlists of music that sync back to Jellyfin | Medium | Planned | | UR-015 | View and manage current audio queue (add, reorder tracks) | Medium | Done | | UR-016 | Change system settings while playing (brightness, volume) | Low | Planned | | UR-017 | Like or unlike audio, albums, movies, etc. | Medium | Done | | UR-018 | Choose to download series, albums, songs, artist discography | Medium | Done | | UR-019 | Resume playback from where you left off (movies, shows, albums) | High | Done | | UR-020 | Select subtitles for video content | High | Planned | | UR-021 | Select audio track for video content | High | Planned | | UR-022 | Control streaming quality and transcoding settings | Medium | Planned | | UR-023 | View "Next Up" / Continue Watching on home screen; auto-play next episode with countdown popup | Medium | In Progress | | UR-024 | View recently added content on server | Medium | Planned | | UR-025 | Sync watch history and progress back to Jellyfin | High | Done | | UR-026 | Sleep timer for audio playback | Low | Planned | | UR-027 | Audio equalizer for sound customization | Low | Planned | | UR-028 | Navigate to artist/album by tapping names in now playing view | High | Done | | UR-029 | Toggle between grid and list view in library | Medium | Done | | UR-030 | Quick genre browsing and filtering | Medium | Done | | UR-031 | Crossfade between audio tracks | Low | Planned (Linux only) | | UR-032 | Gapless playback for seamless album listening | Medium | Done (Linux only) | | UR-033 | Volume normalization to prevent volume jumps between tracks | Low | Done (Linux only) | | UR-034 | Rich home screen with hero banners, carousels, and personalized sections | High | Planned | | UR-035 | View cast/crew (actors, directors) on movie/show detail pages | High | Planned | | UR-036 | Navigate to actor/person page showing their filmography | Medium | Planned | | UR-037 | Visually appealing video library with poster grids and metadata | High | Planned | | UR-038 | Movie/show detail page with backdrop, ratings, and rich metadata | High | Planned | | UR-039 | Navigate between main sections via bottom navigation bar | High | In Progress | --- ## 2. Software Requirements ### 2.1 Integration Requirements External system integrations and platform-specific implementations. | ID | Requirement | Category | Traces To | Status | |----|-------------|----------|-----------|--------| | IR-001 | Build system supporting multiple targets (Linux, Android) | Build | UR-001 | Done | | IR-002 | Build scripts for Android and Linux | Build | UR-001 | Done | | IR-003 | Integration of libmpv for Linux playback | Playback | UR-003, UR-004 | In Progress | | IR-004 | Integration of ExoPlayer for Android playback | Playback | UR-003, UR-004 | In Progress (basic playback works, audio settings missing) | | IR-005 | MPRIS D-Bus integration for Linux lockscreen/media controls | Platform | UR-006 | Planned | | IR-006 | Android MediaSession integration for lockscreen controls | Platform | UR-006 | In Progress | | IR-007 | Bluetooth AVRCP integration via system media session | Platform | UR-006 | Planned | | IR-008 | Android audio focus handling (pause on call) | Platform | UR-004, UR-006 | In Progress | | IR-009 | Jellyfin API client for authentication | API | UR-009, UR-012 | Done | | IR-010 | Jellyfin API client for library browsing | API | UR-007, UR-008 | Done | | IR-011 | Jellyfin API client for playback streaming | API | UR-003, UR-004 | Done | | IR-012 | Jellyfin Sessions API for remote playback control | API | UR-010 | Planned | | IR-021 | Android MediaRouter integration for remote volume in system panel | Platform | UR-010, UR-016 | Planned | | IR-013 | SQLite integration for local database | Storage | UR-002, UR-011 | Done | | IR-014 | Secure credential storage (keyring/keychain) | Security | UR-012 | Done | | IR-015 | Jellyfin API client for playback progress reporting | API | UR-019, UR-025 | Done | | IR-016 | Jellyfin API client for subtitle/audio track info | API | UR-020, UR-021 | Planned | | IR-017 | Jellyfin API client for transcoding parameters | API | UR-022 | Planned | | IR-018 | libmpv subtitle rendering and selection | Playback | UR-020 | Planned | | IR-019 | libmpv audio track selection | Playback | UR-021 | Planned | | IR-020 | libmpv/ExoPlayer equalizer integration | Playback | UR-027 | Planned | | IR-022 | Jellyfin API client for person/cast data | API | UR-035, UR-036 | Planned | | IR-023 | Database schema for person/cast caching | Storage | UR-035, UR-036 | Planned | | IR-024 | Jellyfin API client for home screen data (featured, continue watching) | API | UR-034 | Planned | ### 2.2 Jellyfin API Requirements API endpoints and data contracts required for Jellyfin integration. | ID | Requirement | Endpoint Category | Traces To | Status | |----|-------------|-------------------|-----------|--------| | JA-001 | Server connection and discovery | System | UR-009 | Done | | JA-002 | User authentication (username/password) | Users | UR-009, UR-012 | Done | | JA-003 | Get user library views | UserViews | UR-007 | Done | | JA-004 | Get library items (paginated) | Items | UR-007 | Done | | JA-005 | Get item details and metadata | Items | UR-007 | Done | | JA-006 | Search across libraries | Items | UR-008 | Done | | JA-007 | Get playback info and stream URL | MediaInfo | UR-003, UR-004 | Done | | JA-008 | Get available subtitles for item | MediaInfo | UR-020 | Planned | | JA-009 | Get available audio tracks for item | MediaInfo | UR-021 | Planned | | JA-010 | Report playback start | Sessions | UR-025 | Done | | JA-011 | Report playback progress (periodic) | Sessions | UR-025 | Done | | JA-012 | Report playback stopped | Sessions | UR-025 | Done | | JA-013 | Get resume position for item | UserData | UR-019 | Done | | JA-014 | Get "Next Up" items | Shows | UR-023 | Planned | | JA-015 | Get "Continue Watching" items | Items | UR-023 | Planned | | JA-016 | Get recently added items | Items | UR-024 | Planned | | JA-017 | Mark item as favorite | UserData | UR-017 | Done | | JA-018 | Remove item from favorites | UserData | UR-017 | Done | | JA-019 | Get/create/update playlists | Playlists | UR-014 | Planned | | JA-020 | Add/remove items from playlist | Playlists | UR-014 | Planned | | JA-021 | Get active sessions list | Sessions | UR-010 | Planned | | JA-022 | Send playback commands to remote session (play/pause/stop) | Sessions | UR-010 | Planned | | JA-023 | Send seek command to remote session | Sessions | UR-010 | Planned | | JA-024 | Send next/previous track commands to remote session | Sessions | UR-010 | Planned | | JA-025 | Play specific item on remote session | Sessions | UR-010 | Planned | | JA-026 | Send volume/mute commands to remote session | Sessions | UR-010 | Planned | | JA-027 | Get transcoding options | MediaInfo | UR-022 | Planned | | JA-028 | Get image/artwork URLs | Images | UR-007 | Done | | JA-029 | Get cast/crew for item (actors, directors) | Items | UR-035 | Planned | | JA-030 | Get person details and filmography | Persons | UR-036 | Planned | | JA-031 | Get items by person (actor/director filmography) | Items | UR-036 | Planned | ### 2.3 Development Requirements Internal architecture, components, and application logic. | ID | Requirement | Category | Traces To | Status | |----|-------------|----------|-----------|--------| | DR-001 | Player state machine (idle, loading, playing, paused, seeking, error) | Player | UR-005 | Done | | DR-002 | MediaItem struct tracking source, location, duration, metadata | Player | UR-003, UR-004 | Done | | DR-003 | Source-agnostic media abstraction (Remote, Local, DirectUrl) | Player | UR-002, UR-011 | Done | | DR-004 | PlayerBackend trait for platform-agnostic playback | Player | UR-003, UR-004 | Done | | DR-005 | Queue manager with shuffle, repeat, history | Player | UR-005, UR-015 | Done | | DR-006 | Audio pre-caching for seamless track transitions | Player | UR-004 | Planned | | DR-007 | Library browsing screens (grid view, search, filters) | UI | UR-007, UR-008 | Done | | DR-008 | Album/Series detail view with track listing | UI | UR-007 | Done | | DR-009 | Audio player UI (mini player, full screen) | UI | UR-005 | Done | | DR-010 | Video player UI (fullscreen, controls overlay) | UI | UR-003, UR-005 | Planned | | DR-011 | Search bar with cross-library search | UI | UR-008 | Done | | DR-012 | Local database for media metadata cache | Storage | UR-002 | Done | | DR-013 | Repository pattern for online/offline data access | Storage | UR-002 | Done | | DR-014 | Offline mutation queue for sync-back operations | Storage | UR-002, UR-014, UR-017 | Planned | | DR-015 | Download manager with queue and progress tracking | Storage | UR-011, UR-018 | Done | | DR-016 | Thumbnail caching and sync with server | Storage | UR-007 | Done | | DR-017 | "Manage Downloads" screen for local media management | UI | UR-013 | Done | | DR-018 | Download buttons on library/album/player screens | UI | UR-011, UR-018 | Done | | DR-019 | Playlist creation and editing UI | UI | UR-014 | Planned | | DR-020 | Queue management UI (add, remove, reorder) | UI | UR-015 | Done | | DR-021 | Like/favorite functionality on media items | UI | UR-017 | Done | | DR-022 | Resume position tracking and restoration on play | Player | UR-019 | Done | | DR-023 | Subtitle selection UI in video player | UI | UR-020 | Planned | | DR-024 | Audio track selection UI in video player | UI | UR-021 | Planned | | DR-025 | Quality/transcoding settings UI | UI | UR-022 | Planned | | DR-026 | "Continue Watching" / "Next Up" home section | UI | UR-023 | Planned | | DR-027 | "Recently Added" home section | UI | UR-024 | Planned | | DR-028 | Playback progress sync service (periodic reporting) | Player | UR-025 | Done | | DR-029 | Sleep timer with countdown and auto-stop | Player | UR-026 | Planned | | DR-030 | Equalizer UI with presets and custom bands | UI | UR-027 | Planned | | DR-031 | Clickable artist/album links in now playing view | UI | UR-028 | Done | | DR-032 | List view option for library browsing (albums, artists) | UI | UR-029 | Done | | DR-033 | Genre browsing screen with quick filters | UI | UR-030 | Done | | DR-034 | Crossfade engine with configurable duration (0-12s) | Player | UR-031 | Planned | | DR-035 | Gapless playback between sequential tracks | Player | UR-032 | Done | | DR-036 | Volume normalization with preset levels (Loud/Normal/Quiet) | Player | UR-033 | Done | | DR-037 | Remote session browser and control UI | UI | UR-010 | Planned | | DR-038 | Home screen with hero banner carousel (featured/continue watching) | UI | UR-034 | Planned | | DR-039 | Home screen horizontal carousels (recently added, recommendations) | UI | UR-034, UR-024 | Planned | | DR-040 | Cast/crew section on movie/show detail pages | UI | UR-035 | Planned | | DR-041 | Person/actor detail page with filmography grid | UI | UR-036 | Planned | | DR-042 | Video library grid with poster cards, year, and rating badges | UI | UR-037 | Planned | | DR-043 | Movie/show detail page with backdrop hero, synopsis, and metadata | UI | UR-038 | Planned | | DR-044 | Horizontal scrolling actor/cast row with profile images | UI | UR-035 | Planned | | DR-045 | Bottom navigation bar with Home, Library, Search buttons | UI | UR-039 | In Progress | | DR-046 | Dedicated search page with input and results | UI | UR-039 | In Progress | | DR-047 | Next episode auto-play popup with configurable countdown | Player | UR-023 | In Progress | | DR-048 | Video settings (auto-play toggle, countdown duration) | Settings | UR-023, UR-026 | In Progress | --- ## 3. Traceability Matrix ### User Requirements to Software Requirements | User Req | Integration Requirements | Development Requirements | |----------|-------------------------|-------------------------| | UR-001 | IR-001, IR-002 | - | | UR-002 | IR-013 | DR-003, DR-012, DR-013, DR-014 | | UR-003 | IR-003, IR-004, IR-011 | DR-002, DR-004, DR-010 | | UR-004 | IR-003, IR-004, IR-008, IR-011 | DR-002, DR-004, DR-006 | | UR-005 | - | DR-001, DR-005, DR-009 | | UR-006 | IR-005, IR-006, IR-007, IR-008 | - | | UR-007 | IR-010 | DR-007, DR-008, DR-016 | | UR-008 | IR-010 | DR-007, DR-011 | | UR-009 | IR-009, IR-010, IR-011 | - | | UR-010 | IR-012, IR-021 | DR-037 | | UR-011 | IR-013 | DR-003, DR-015, DR-018 | | UR-012 | IR-009, IR-014 | - | | UR-013 | IR-013 | DR-017 | | UR-014 | - | DR-014, DR-019 | | UR-015 | - | DR-005, DR-020 | | UR-016 | - | - | | UR-017 | - | DR-014, DR-021 | | UR-018 | IR-013 | DR-015, DR-018 | | UR-019 | IR-015 | DR-022 | | UR-020 | IR-016, IR-018 | DR-023 | | UR-021 | IR-016, IR-019 | DR-024 | | UR-022 | IR-017 | DR-025 | | UR-023 | IR-010 | DR-026, DR-047, DR-048 | | UR-024 | IR-010 | DR-027 | | UR-025 | IR-015 | DR-028 | | UR-026 | - | DR-029, DR-048 | | UR-027 | IR-020 | DR-030 | | UR-028 | - | DR-031 | | UR-029 | - | DR-032 | | UR-030 | IR-010 | DR-033 | | UR-031 | - | DR-034 | | UR-032 | - | DR-035 | | UR-033 | - | DR-036 | | UR-034 | IR-010, IR-024 | DR-038, DR-039 | | UR-035 | IR-022, IR-023 | DR-040, DR-044 | | UR-036 | IR-022, IR-023 | DR-041 | | UR-037 | IR-010 | DR-042 | | UR-038 | IR-010 | DR-043 | | UR-039 | - | DR-045, DR-046 | --- ## 4. Test Traceability ### Unit Tests to Software Requirements | Test ID | Test Description | Traces To | Status | |---------|-----------------|-----------|--------| | UT-001 | Player state transitions | DR-001 | Pending | | UT-002 | MediaItem source URL resolution | DR-002, DR-003 | Pending | | UT-003 | Queue next/previous navigation | DR-005 | Pending | | UT-004 | Queue shuffle order generation | DR-005 | Pending | | UT-005 | Queue repeat mode behavior | DR-005 | Pending | | UT-006 | Jellyfin authentication flow | IR-009 | Pending | | UT-007 | Jellyfin library items parsing | IR-010 | Pending | | UT-008 | Repository pattern online/offline switching | DR-013 | Pending | | UT-009 | Offline mutation queue persistence | DR-014 | Pending | | UT-010 | Download queue management | DR-015 | Done | | UT-011 | Resume position storage and retrieval | DR-022 | Pending | | UT-012 | Sleep timer countdown logic | DR-029 | Pending | | UT-013 | Playback progress reporting throttling | DR-028 | Pending | | UT-014 | Database open and in-memory mode | IR-013, DR-012 | Done | | UT-015 | Database migrations run successfully | IR-013, DR-012 | Done | | UT-016 | All database tables created | IR-013, DR-012 | Done | | UT-017 | FTS5 search table created | IR-013, DR-012 | Done | | UT-018 | Server CRUD operations | IR-013, DR-012 | Done | | UT-019 | User CRUD operations | IR-013, DR-012 | Done | | UT-020 | Cascade delete server removes users | IR-013, DR-012 | Done | | UT-021 | Item insert and FTS search | IR-013, DR-012 | Done | | UT-022 | User data playback position storage | IR-013, DR-012, DR-022 | Done | | UT-023 | Sync queue operations | IR-013, DR-014 | Done | | UT-024 | Downloads table operations | IR-013, DR-015 | Done | | UT-025 | Migrations are idempotent | IR-013, DR-012 | Done | | UT-026 | NullBackend volume default value | DR-004 | Done | | UT-027 | NullBackend set volume | DR-004 | Done | | UT-028 | NullBackend volume clamping (high/low) | DR-004 | Done | | UT-029 | NullBackend volume boundary values | DR-004 | Done | | UT-030 | PlayerController volume default | DR-004, DR-009 | Done | | UT-031 | PlayerController set volume | DR-004, DR-009 | Done | | UT-032 | PlayerController muted default | DR-004, DR-009 | Done | | UT-033 | PlayerController volume delegates to backend | DR-004, DR-009 | Done | | UT-034 | Download event serialization roundtrip | DR-015 | Done | | UT-035 | Download event completed serialization | DR-015 | Done | | UT-036 | Download event failed serialization | DR-015 | Done | | UT-037 | Download worker exponential backoff | DR-015 | Done | | UT-038 | Download worker error retryable check | DR-015 | Done | | UT-039 | Download manager creation | DR-015 | Done | | UT-040 | Download manager set max concurrent | DR-015 | Done | | UT-041 | Download info serialization | DR-015 | Done | | UT-042 | Download command filename sanitization | DR-015, DR-018 | Done | | UT-043 | Download command filename extension preservation | DR-015, DR-018 | Done | | UT-044 | Offline item serialization | DR-017 | Done | | UT-045 | Smart cache default config | DR-015 | Done | | UT-046 | Smart cache album affinity tracking | DR-015 | Done | | UT-047 | Smart cache queue precache config | DR-015 | Done | | UT-048 | Smart cache storage limit check | DR-015 | Done | ### Integration Tests | Test ID | Test Description | Traces To | Status | |---------|-----------------|-----------|--------| | IT-001 | End-to-end authentication with Jellyfin server | IR-009, UR-009 | Pending | | IT-002 | Library browsing and item loading | IR-010, UR-007 | Pending | | IT-003 | Audio playback via libmpv | IR-003, UR-004 | Pending | | IT-004 | Video playback via libmpv | IR-003, UR-003 | Pending | | IT-005 | MPRIS lockscreen controls on Linux | IR-005, UR-006 | Pending | | IT-006 | Offline mode with local database | IR-013, UR-002 | Pending | | IT-007 | Media download and local playback | DR-015, UR-011 | Pending | | IT-008 | Subtitle track selection via libmpv | IR-018, UR-020 | Pending | | IT-009 | Audio track selection via libmpv | IR-019, UR-021 | Pending | | IT-010 | Playback progress sync to Jellyfin | IR-015, UR-025 | Pending | | IT-011 | Resume playback from server position | IR-015, UR-019 | Pending | | IT-012 | Equalizer bands via libmpv | IR-020, UR-027 | Pending | --- ## 5. Development Commands ```bash # Activate Rust environment (fish shell) source "$HOME/.cargo/env.fish" # Install dependencies bun install # Development bun run tauri dev # Type checking bun run check # Build for Linux bun run tauri build # Build for Android bun run tauri android build ``` --- ## 6. Architecture Overview ``` jellytau/ ├── src/ # Svelte frontend │ ├── lib/ │ │ ├── api/ # Jellyfin API client (repository pattern) │ │ ├── components/ # UI components (player, library) │ │ └── stores/ # Svelte stores (auth, library, player, queue) │ └── routes/ # SvelteKit pages ├── src-tauri/ # Rust backend │ ├── src/ │ │ ├── commands/ # Tauri commands │ │ └── player/ # Player architecture │ │ ├── state.rs # State machine │ │ ├── media.rs # MediaItem, MediaSource │ │ ├── queue.rs # Queue management │ │ └── backend.rs # PlayerBackend trait │ └── gen/android/ # Android project └── README.md ``` --- ## 7. Technical Debt ### Linux Keyring Integration Workaround **Issue**: The `keyring-rs` crate (v3.x) has issues with retrieving credentials from the Linux Secret Service API, despite successfully saving them. **Symptoms**: - Credentials are saved to the system keyring successfully (verified with `secret-tool search`) - Retrieval via the `keyring-rs` library fails with `NoEntry` error - Session restoration fails on app restart even though credentials exist **Root Cause**: The `keyring-rs` library's Linux backend doesn't correctly retrieve entries from the Secret Service that it previously stored. This appears to be a bug in how the library interfaces with the Secret Service D-Bus API. **Current Workaround**: We bypass the `keyring-rs` library on Linux and use direct system calls to `secret-tool`: - **Save**: `secret-tool store --label