jellytau/PRELOADING.md

213 lines
6.4 KiB
Markdown

# Smart Preloading Implementation
This document describes the smart preloading system that automatically queues downloads for upcoming tracks in the playback queue.
## Overview
The preloading system monitors playback and automatically queues background downloads for the next 3 tracks in the queue. This ensures smooth playback transitions and offline availability without requiring manual downloads.
## Architecture
### Backend (Rust)
**Smart Cache Engine** - `/src-tauri/src/download/cache.rs`
- Manages preload configuration
- Default settings: preload 3 tracks, works on any connection (not wifi-only)
- Storage limit: 10GB
- Album affinity tracking (future feature)
**Queue Manager** - `/src-tauri/src/player/queue.rs`
- New method: `get_upcoming(count)` returns next N tracks
- Respects shuffle order
- Handles repeat modes (Off, All, One)
- Wraps around when RepeatMode::All is enabled
**Preload Command** - `/src-tauri/src/commands/player.rs`
- `player_preload_upcoming` - Main preload endpoint
- Checks SmartCache configuration
- Gets upcoming tracks from queue
- Skips already downloaded/queued items
- Queues new downloads with low priority (-100)
- Returns stats: queued_count, already_downloaded, skipped
**Configuration Commands**
- `player_set_cache_config` - Update preload settings
- `player_get_cache_config` - Get current settings
### Frontend (TypeScript/Svelte)
**Preload Service** - `/src/lib/services/preload.ts`
- Main function: `preloadUpcomingTracks()`
- Automatically gets current user ID from auth store
- Calls backend preload command
- Fails silently - never interrupts playback
- Logs meaningful results only
**Integration Points** - `/src/lib/services/playerEvents.ts`
1. **On playback start** - When state changes to "playing"
2. **On track advance** - After successfully advancing to next track
## How It Works
### Playback Flow
```
User plays track/queue
Backend starts playback
Emits "state_changed" event with "playing"
playerEvents.handleStateChanged() catches event
Calls preloadUpcomingTracks()
Backend queues downloads for next 3 tracks (if not already downloaded)
```
### Track Advance Flow
```
Track ends (or user clicks next)
playerEvents.handlePlaybackEnded() or manual next()
Calls player_next backend command
Backend plays next track, emits "state_changed"
Calls preloadUpcomingTracks() again
Queue is shifted forward, new track gets preloaded
```
## Configuration
### Default Settings
```typescript
{
queuePrecacheEnabled: true,
queuePrecacheCount: 3,
albumAffinityEnabled: true,
albumAffinityThreshold: 3,
storageLimit: 10737418240, // 10GB
wifiOnly: false
}
```
### Updating Configuration
```typescript
import { updateCacheConfig } from '$lib/services/preload';
await updateCacheConfig({
queuePrecacheCount: 5, // Preload 5 tracks instead of 3
wifiOnly: true // Only preload on WiFi
});
```
## Features
### Intelligent Queueing
- ✅ Checks if tracks are already downloaded
- ✅ Skips tracks already in download queue
- ✅ Low priority (-100) so user-initiated downloads go first
- ✅ Respects shuffle and repeat modes
- ✅ No duplicate downloads
### Offline First
- ✅ Existing `create_media_item()` in player.rs checks local downloads first
- ✅ Preloading ensures next tracks become local over time
- ✅ Seamless offline playback without manual intervention
### Non-Intrusive
- ✅ Background operation - never blocks playback
- ✅ Fails silently - errors are logged but don't affect UX
- ✅ Automatic - no user interaction required
- ✅ Configurable - users can adjust or disable
## Files Changed
### Backend
- `src-tauri/src/player/queue.rs` - Added `get_upcoming()` method
- `src-tauri/src/download/cache.rs` - Made `CacheConfig` serializable, updated defaults
- `src-tauri/src/commands/player.rs` - Added preload commands and `SmartCacheWrapper`
- `src-tauri/src/lib.rs` - Initialized SmartCache, registered commands
### Frontend
- `src/lib/services/preload.ts` - New preload service (created)
- `src/lib/services/playerEvents.ts` - Integrated preload triggers
### Configuration
- `src-tauri/Cargo.toml` - Added tempfile dev dependency for tests
## Testing
### Rust Tests
```bash
cd src-tauri
cargo test queue::tests::test_get_upcoming
cargo test cache::tests::test_default_config
```
All tests pass ✅
### Manual Testing
1. **Start playback**
- Play a queue of 5+ tracks
- Check console for: `[Preload] Queued N track(s) for background download`
- Verify download queue shows 3 pending downloads with priority -100
2. **Track advance**
- Let track finish or click next
- Check console for new preload log
- Verify queue shifts (old track 2 becomes current, new track gets queued)
3. **Repeat mode**
- Enable Repeat All
- Play to end of queue
- Verify wraps around and continues preloading
4. **Already downloaded**
- Download all tracks in an album
- Play the album
- Check logs show: `already_downloaded: 3, queued: 0`
## Future Enhancements
1. **Album Affinity** - If user plays 3+ tracks from an album, auto-download the rest
2. **WiFi Detection** - Respect `wifi_only` setting on mobile
3. **Storage Management** - Auto-evict LRU items when storage limit reached
4. **Smart Priority** - Boost priority as track gets closer in queue
5. **Bandwidth Throttling** - Limit download speed to not interfere with streaming
## Troubleshooting
### Preload not working
- Check console for `[Preload]` logs
- Verify user is logged in: `auth.getUserId()` returns value
- Check SmartCache config: `queuePrecacheEnabled` should be true
### Downloads not starting
- Preload only queues downloads, doesn't start them
- Check download manager is processing queue
- Verify backend has download worker running
### Too many downloads
- Reduce `queuePrecacheCount` in config
- Enable `wifiOnly` mode
- Adjust `storageLimit`
## Performance Impact
- **Minimal** - Background downloads use low priority
- **Non-blocking** - Async operation, no playback delay
- **Bandwidth-friendly** - Only downloads when needed
- **Storage-aware** - Respects configured limits
## Summary
Smart preloading transforms JellyTau into an offline-first music player. By automatically queueing downloads for upcoming tracks, it ensures seamless playback and offline availability without requiring users to manually manage downloads. The system is intelligent (checks what's already downloaded), non-intrusive (fails silently), and configurable (users can adjust or disable).