Cover Art System - Overview¶
Purpose¶
The cover art system manages the extraction, optimization, caching, and serving of album artwork for the Mixtape Society application. It provides responsive, bandwidth-optimized images for different platforms and use cases.
Key Features¶
- Automatic Extraction - Finds cover art from folder images or embedded metadata
- Size Optimization - Generates 6 standard sizes (96×96 to 512×512)
- Lazy Generation - Creates variants only when requested
- Permanent Caching - Stores optimized images for fast subsequent loads
- Fallback Handling - Graceful degradation when covers unavailable
- Platform Optimization - Serves appropriate sizes for iOS, Android Auto, and desktop
System Architecture¶
graph TD
A[Music File] --> B[Cover Extraction]
B --> C{Cover Found?}
C -->|Yes| D[Generate Main Cover 800px]
C -->|No| E[Use Fallback]
D --> F[Cache Main Cover]
F --> G{Size Variant Requested?}
G -->|Yes| H[Generate Variants]
G -->|No| I[Serve Main Cover]
H --> J[Cache All Variants]
J --> K[Serve Requested Size]
E --> I
Components¶
1. Extraction (reader.py)¶
Located in src/musiclib/reader.py, the MusicCollection class handles cover extraction:
Methods:
get_cover(release_dir)- Returns single cover URLget_cover_sizes(release_dir)- Returns all size variants_extract_cover(release_dir, target_path)- Extracts from files_generate_cover_variants(release_dir, slug)- Creates size variants
Extraction Priority:
- Common image files (
cover.jpg,folder.jpg,album.jpg) - Embedded artwork from audio files
- Fallback image
Optimization:
- Resizes to max 800×800px
- Converts to RGB JPEG
- Compresses to 85% quality
- Limits file size to 500KB
2. Storage¶
Cache Directory: DATA_ROOT/cache/covers/
File Naming:
{slug}.jpg # Main cover (800px max)
{slug}_96x96.jpg # Thumbnail variant
{slug}_128x128.jpg # Small variant
{slug}_192x192.jpg # Medium variant
{slug}_256x256.jpg # Android Auto optimal
{slug}_384x384.jpg # High-DPI variant
{slug}_512x512.jpg # Full-screen variant
_fallback.jpg # Default when no cover found
Slug Generation:
- Sanitizes release directory to safe filename
- Replaces special characters with underscores
- Truncates long paths (>200 chars)
- Adds hash suffix for collision avoidance
3. Serving (app.py)¶
Two Flask routes serve cover images:
Direct Serving: /covers/<filename>
- Original endpoint (unchanged)
- Serves cached files directly
- Simple, fast file delivery
API Serving: /api/covers/<release_dir>?size=
- New size-parameterized endpoint
- Generates variants on-demand
- Returns appropriate size or fallback
See: Cover Art Routes
Standard Sizes¶
| Size | Dimensions | Use Case | Typical Size |
|---|---|---|---|
| Tiny | 96×96 | Thumbnails in lists | 5-8 KB |
| Small | 128×128 | Small tiles | 8-12 KB |
| Small-Medium | 192×192 | Medium tiles | 15-20 KB |
| Medium | 256×256 | Android Auto optimal | 30-50 KB |
| Large | 384×384 | High-DPI displays | 60-90 KB |
| Extra Large | 512×512 | Full-screen player | 100-150 KB |
Workflow¶
First Request (Cold Cache)¶
sequenceDiagram
participant Client
participant Flask
participant Extraction
participant FileSystem
participant Cache
Client->>Flask: GET /api/covers/Artist/Album?size=256x256
Flask->>Cache: Check for variant
Cache-->>Flask: Not found
Flask->>Cache: Check for main cover
Cache-->>Flask: Not found
Flask->>Extraction: Extract cover from files
Extraction->>FileSystem: Search folder images
alt Image found
FileSystem-->>Extraction: cover.jpg
else No image
Extraction->>FileSystem: Check embedded art
FileSystem-->>Extraction: Audio file metadata
end
Extraction->>Extraction: Optimize to 800x800, 85% quality
Extraction->>Cache: Save main cover
Flask->>Extraction: Generate all variants
Extraction->>Extraction: Resize to 96×96, 128×128, ..., 512×512
Extraction->>Cache: Save all variants
Cache-->>Flask: Variant ready
Flask-->>Client: 256×256 JPEG (~40KB)
Total time: ~150-300ms (one-time cost)
Subsequent Requests (Warm Cache)¶
sequenceDiagram
participant Client
participant Flask
participant Cache
Client->>Flask: GET /api/covers/Artist/Album?size=256x256
Flask->>Cache: Check for variant
Cache-->>Flask: Found!
Flask-->>Client: 256×256 JPEG (~40KB)
Total time: ~5-10ms (served from cache)
Performance Characteristics¶
Storage Impact¶
Per album:
- Main cover: 300-500 KB
- All 6 variants: 50-150 KB
- Total increase: ~50-150 KB per album
For 1000 albums:
- Main covers: ~400 MB
- All variants: ~100 MB
- Total: ~500 MB
Bandwidth Savings¶
Android Auto (256×256):
- Before: 400 KB per cover
- After: 40 KB per cover
- Savings: 90%
Mobile Web (128×128):
- Before: 400 KB per cover
- After: 12 KB per cover
- Savings: 97%
10-track mixtape on Android Auto:
- Before: 4 MB
- After: 400 KB
- Savings: 90%
Generation Performance¶
| Operation | First Request | Cached Request |
|---|---|---|
| Main cover extraction | 50-100ms | 0ms |
| Variant generation | 100-200ms | 0ms |
| File serving | 5-10ms | 5-10ms |
| Total | 150-300ms | 5-10ms |
Platform Optimization¶
The system automatically selects appropriate sizes based on the requesting platform:
iOS¶
Prioritizes larger sizes for high-quality lock screen display:
- 512×512 (primary)
- 256×256 (secondary)
- 192×192 (fallback)
Android Auto¶
Provides full spectrum for optimal selection:
- 96×96 (minimum required)
- 128×128, 192×192, 256×256 (optimal range)
- 384×384, 512×512 (high quality)
Desktop¶
Simplified set for standard displays:
- 192×192 (thumbnails/tiles)
- 512×512 (full player)
Error Handling¶
Extraction Failures¶
No cover found:
- Search common image files → Not found
- Check embedded artwork → Not found
- Result: Return
_fallback.jpg
Extraction error:
- Log warning message
- Return
_fallback.jpg - Result: User never sees broken image
Generation Failures¶
Variant generation fails:
- Log warning message
- Return main cover (800px) instead
- Retry on next request
- Result: Slightly larger file, but still functional
Missing Files¶
Requested file doesn't exist:
- Try to generate from main cover
- If main cover missing, extract from audio
- If extraction fails, return fallback
- Result: Multiple fallback levels ensure images always load
Integration Points¶
Backend (Python)¶
from musiclib import MusicCollection
# Initialize collection
mc = MusicCollection(music_root="/music", db_path="/data/music.db")
# Get single cover URL (original behavior)
cover_url = mc.get_cover("Artist/Album")
# Returns: "covers/artist_album.jpg"
# Get all size variants (new behavior)
cover_sizes = mc.get_cover_sizes("Artist/Album")
# Returns: {
# "96x96": "covers/artist_album_96x96.jpg",
# "256x256": "covers/artist_album_256x256.jpg",
# ...
# }
Frontend (JavaScript)¶
// Extract metadata with platform-optimized artwork
const metadata = extractMetadataFromDOM(trackElement);
// metadata.artwork contains size-specific URLs:
// [
// { src: "/covers/slug_96x96.jpg", sizes: "96x96", type: "image/jpeg" },
// { src: "/covers/slug_256x256.jpg", sizes: "256x256", type: "image/jpeg" },
// ...
// ]
// Update MediaSession
navigator.mediaSession.metadata = new MediaMetadata({
title: metadata.title,
artist: metadata.artist,
artwork: metadata.artwork // Browser picks best size
});
Flask Routes¶
# Direct file serving (existing)
@app.route("/covers/<filename>")
def serve_album_cover(filename):
return send_from_directory(covers_dir, filename)
# Size-parameterized API (new)
@app.route("/api/covers/<path:release_dir>")
def serve_cover_by_size(release_dir):
size = request.args.get('size') # e.g., "256x256"
# ... generate if needed, return appropriate file
Related Documentation¶
Technical Details:
- Size Optimization Implementation - Code-level details
- API Reference - Complete API documentation
Integrated with:
- Cover Art Routes - HTTP endpoint documentation
- Playback Routes - Audio streaming context
- Android Auto
Future Enhancements¶
Potential improvements to the cover art system:
- WebP format support - Better compression for modern browsers
- AVIF format support - Next-gen image format
- Automatic format selection - Serve WebP/AVIF to supporting browsers
- Custom size requests - Allow arbitrary dimensions with limits
- Bulk pre-generation - Background job for popular albums
- CDN integration - Serve from CDN for better global performance
- Smart caching - Delete unused variants after N days
- Analytics - Track most-requested sizes
- Color extraction - Dominant colors for UI theming
- Multiple covers - Support for disc-specific artwork
