Skip to content

amgno/cornocopia

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cornocopia Music Player

Overview

Cornocopia is a web-based music player application that combines classic iTunes-inspired interface design with modern AI-powered playlist generation and music recommendation capabilities. The system consists of a React-based frontend and an Express.js backend that integrates with the Anthropic Claude API for intelligent music curation.

Screenshots

Main Interface

Main Window iTunes-inspired interface with draggable window, LCD display, and brushed metal controls

AI Playlists

AI Playlists Sidebar Automatically generated playlists organized by genre, year, and energy

AI Next Notification

AI Next Song Notification Real-time notification when AI selects the next track (20 seconds before transition)

Grid View

Grid View Album grid view with hover interactions

Architecture

System Components

The application follows a client-server architecture with the following stack:

Frontend:

  • React 18.2.0 with functional components and hooks
  • Vite 5.0 as build tool and development server
  • Tailwind CSS 3.3.5 for utility-first styling
  • Lucide React 0.292.0 for iconography

Backend:

  • Node.js with Express 4.18.2
  • Anthropic SDK 0.24.0 for AI integration
  • music-metadata 7.13.4 for audio file parsing
  • node-cache 5.1.2 for in-memory caching
  • fs-extra 11.1.1 for filesystem operations

Infrastructure:

  • Docker containerization with multi-stage builds
  • Nginx as reverse proxy for frontend
  • Volume mounting for music library and persistent data

Data Flow

Client Request → Express Server → Music Metadata Parser → Library Scan
                      ↓
                 Claude API → Playlist Generation → Cache Manager
                      ↓
                 JSON Response → React State → UI Update

Core Functionality

Music Library Management

The server scans a mounted /music directory recursively, parsing audio files with the following extensions: .mp3, .flac, .wav, .m4a, .alac. For each file, the system extracts:

  • Title, artist, album metadata
  • Genre tags (array)
  • Year of release
  • Duration in seconds
  • Audio format specifications
  • Embedded or external album artwork

Album art is resolved through a priority system:

  1. Embedded picture data in audio file metadata
  2. cover.jpg in the same directory
  3. folder.jpg in the same directory

The library is served via REST API at /api/library and cached client-side for performance.

AI Playlist Generation

Algorithm Design

The playlist generation system uses a two-tier approach:

Primary Method: Claude AI Analysis

The system sends the complete music library metadata to Claude with a structured prompt that instructs the model to:

  1. Analyze musical coherence rather than artist or album grouping
  2. Create thematic playlists based on:
    • Genre compatibility
    • Temporal cohesion (decade-based grouping)
    • Energy and mood characteristics
  3. Ensure variety by limiting consecutive tracks from the same album to 2-3 maximum
  4. Generate 10-30 tracks per playlist
  5. Output structured JSON with playlist metadata

The prompt engineering specifically prohibits album-centric grouping to avoid creating playlists that simply mirror album tracklists. Instead, the AI is instructed to evaluate individual tracks for their fit within a broader musical context.

Secondary Method: Fallback Algorithm

When the Claude API is unavailable or fails, a deterministic fallback algorithm activates:

  1. Group tracks by genre tags
  2. Group tracks by decade (floor of year/10)
  3. Apply a diversification function that:
    • Shuffles tracks randomly
    • Filters consecutive tracks from the same album
    • Maintains a maximum of 2 consecutive tracks per album
    • Limits playlists to 30 tracks

Caching Strategy

Generated playlists are persisted to disk at /app/data/playlists.json with the following cache invalidation logic:

  • Cache TTL: 7 days (configurable via environment variable)
  • Invalidation trigger: Library hash change
  • Hash calculation: MD5 of concatenated file paths, sizes, and modification timestamps

This ensures playlists regenerate only when the library content changes, minimizing API costs while maintaining accuracy.

AI Next Song Selection

Selection Algorithm

The AI Next Song feature implements an intelligent track sequencing system with predictive preloading:

Preload Timing: The system initiates AI selection 20 seconds before the current track ends. This allows:

  • API request completion during playback
  • Seamless transition between tracks
  • Zero-gap playback experience
  • User notification of upcoming selection

Selection Criteria:

  1. Current track characteristics (genre, artist, year, album)
  2. Recent playback history (last 5 tracks to avoid repetition)
  3. Available library subset (smart sampling)

Library Sampling Optimization:

To reduce API token consumption for large libraries, the system implements weighted sampling:

  • 50% of sample: tracks matching current genre
  • 30% of sample: tracks from the same decade
  • 20% of sample: random selection
  • Maximum sample size: 150 tracks

This maintains recommendation quality while reducing API payload size by up to 90% for large libraries.

Response Handling:

The system implements a 3-second timeout with automatic fallback. The fallback algorithm:

  1. Filters recently played tracks
  2. Prioritizes same-genre tracks
  3. Secondarily prioritizes same-decade tracks
  4. Selects randomly from the filtered pool

Caching Layer

AI Next Song selections are cached in-memory using node-cache with:

  • Cache key: MD5 hash of (current_song_path + recent_history)
  • TTL: 24 hours
  • Expected hit rate: 60-75%

This provides instant responses for repeated contexts while allowing fresh recommendations for new scenarios.

User Notifications

When AI Next selects a track, the system displays a temporary notification toast containing:

  • Selected track title and artist
  • Indicator of AI selection vs fallback algorithm
  • 3-second display duration with slide-in animation
  • Color-coded by selection type (green for AI, yellow for fallback)

The notification appears in the top-right corner without obstructing playback controls or library view.

Playlist Mode Implementation

The application implements a queue-based playlist playback system:

State Management:

currentPlaylistQueue: {
  playlistId: string,
  songs: Array<Song>,
  currentIndex: number
}
playlistMode: boolean

Playback Priority:

The playNext() function implements the following decision tree:

  1. If playlistMode is active:
    • Increment queue index
    • Play next track in queue
    • If queue exhausted, exit playlist mode
  2. Else if aiNextEnabled:
    • Call AI selection API
    • Play recommended track
  3. Else:
    • Sequential library playback

This ensures playlist continuity takes precedence over other playback modes.

Interface Design

Visual Language: iTunes Skeuomorphism

The interface recreates the iTunes 11-12 era aesthetic through several design principles:

Window Chrome

The application uses a draggable window paradigm despite being web-based:

  • Custom title bar with macOS-style traffic light buttons (red, yellow, green)
  • Window shadow and border radius for depth perception
  • Absolute positioning with transform for smooth dragging
  • Mouse event handling for drag state management

Implementation uses React state for position tracking and event listeners for mousemove/mouseup events.

Material Simulation

Brushed Metal Gradient:

The top control area simulates brushed aluminum through CSS gradients:

background: linear-gradient(to bottom, #3a3a3a 0%, #2a2a2a 50%, #1a1a1a 100%)

This creates the perception of light reflection across a non-uniform metallic surface.

LCD Display:

The center information panel mimics a backlit LCD screen:

  • Dark background (#0f0f0f) for contrast
  • Inset shadow for depth illusion
  • Monochromatic color scheme (white/gray text)
  • Fixed-width font for time display

Physical Buttons:

Control buttons simulate 3D depth through:

  • Gradient fills (lighter top, darker bottom)
  • Border definition
  • Box shadow for elevation
  • Active state transform (translateY) for press feedback

Layout Structure

Three-Column Layout:

┌─────────────────────────────────────────┐
│         Title Bar (Draggable)           │
├─────────────────────────────────────────┤
│         Controls + LCD Display          │
├──────────┬────────────────┬─────────────┤
│          │                │             │
│ Sidebar  │  Content Area  │             │
│          │                │             │
└──────────┴────────────────┴─────────────┘
│            Status Bar                   │
└─────────────────────────────────────────┘

Sidebar:

  • Fixed width (224px)
  • Dark background (#252525)
  • Hierarchical navigation with collapsible sections
  • Selection highlighting with iTunes blue (#3d8dd5)

Content Area:

  • List view: Table-based layout with alternating row colors
  • Grid view: CSS Grid with aspect-ratio preserved album art
  • Album headers in list view for grouping

Status Bar:

  • Fixed height (24px)
  • Dark background matching window chrome
  • Contextual information display (track count, playlist status, AI indicators)

Typography and Spacing

The interface uses system fonts for native appearance:

font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif

Text hierarchy:

  • Headers: 12px, uppercase, letter-spacing
  • Body: 12-14px, regular weight
  • Status: 10-11px, tabular numerals for time display

Spacing follows an 8px grid system with exceptions for pixel-perfect alignment with historical iTunes layouts.

Color Palette

The application uses a restricted palette for visual cohesion:

Backgrounds:

  • Window: #2a2a2a
  • Content: #1e1e1e
  • Sidebar: #252525
  • LCD: #0f0f0f

Accents:

  • Selection: #3d8dd5 (iTunes blue)
  • AI Indicators: #60a5fa (blue-400)
  • Playlist Mode: #4ade80 (green-400)

Text:

  • Primary: #e5e5e5 (gray-200)
  • Secondary: #9ca3af (gray-400)
  • Tertiary: #6b7280 (gray-500)

Interactive States

All interactive elements implement hover and active states:

  • Hover: Brightness adjustment or background color change
  • Active: Vertical translation (1px) for button press simulation
  • Focus: Border color change for keyboard navigation
  • Selection: Background fill with iTunes blue

API Endpoints

Library Management

GET /api/library

Returns complete music library with metadata.

Response structure:

[
  {
    "path": "/Artist/Album/01. Track.flac",
    "name": "01. Track.flac",
    "title": "Track Title",
    "artist": "Artist Name",
    "album": "Album Name",
    "genre": ["Genre1", "Genre2"],
    "year": 2024,
    "duration": 245.6,
    "format": { ... },
    "hasArt": true
  }
]

GET /api/art/{path}

Streams album artwork for specified track path. Returns JPEG/PNG binary data or 404 if unavailable.

GET /api/stream/{path}

Streams audio file with proper MIME type headers. Supports range requests for seeking.

Playlist Management

GET /api/playlists

Returns all generated playlists or triggers generation if cache is invalid.

Response structure:

{
  "playlists": [
    {
      "id": "uuid",
      "name": "Playlist Name",
      "description": "Description text",
      "category": "genre|year|mood",
      "metadata": {},
      "songs": ["/path/to/track.flac"],
      "createdAt": "2024-12-05T...",
      "generatedBy": "ai|fallback",
      "version": 1
    }
  ],
  "lastGenerated": "2024-12-05T...",
  "status": "ready|generating|error"
}

POST /api/playlists/regenerate

Forces playlist regeneration, clearing cache.

Request body:

{
  "force": true
}

Response:

{
  "status": "started",
  "estimatedTime": 15
}

GET /api/playlists/status

Returns current generation progress.

Response:

{
  "isGenerating": true,
  "progress": 45,
  "currentStep": "Generating playlists with AI"
}

AI Features

POST /api/ai-next-song

Requests AI-powered next track selection.

Request body:

{
  "currentSong": {
    "path": "/path/to/current.flac",
    "title": "Current Track",
    "artist": "Artist",
    "album": "Album",
    "genre": ["Genre"],
    "year": 2024,
    "duration": 245
  },
  "recentHistory": ["/path1", "/path2"],
  "library": [ /* full library metadata */ ]
}

Response:

{
  "nextSong": "/path/to/next.flac",
  "reason": "Genre compatibility and energy match",
  "fallback": false,
  "cacheHit": true,
  "duration": 45
}

Configuration

Environment Variables

ANTHROPIC_API_KEY (required)

PLAYLIST_CACHE_TTL (optional)

  • Cache time-to-live in seconds
  • Default: 604800 (7 days)

MAX_PLAYLIST_SIZE (optional)

  • Maximum tracks per generated playlist
  • Default: 30

Docker Volumes

Music Library:

volumes:
  - ./music:/music:ro

Mount music files at /music. Read-only recommended for safety.

Persistent Data:

volumes:
  - ./data:/app/data

Stores generated playlists and cache data at /app/data.

Performance Characteristics

Client-Side

  • Initial load time: ~200ms (cached assets)
  • Library fetch: ~100-500ms (depends on library size)
  • Playlist generation trigger: ~50ms (async operation)
  • UI responsiveness: 60fps target for dragging and scrolling
  • Memory footprint: ~50-100MB (depends on library size)

Server-Side

  • Library scan: ~100ms per 100 tracks
  • Playlist generation (AI): ~10-30s for 100 tracks
  • Playlist generation (fallback): ~100-500ms
  • AI Next Song: 1-3s (with 3s timeout)
  • Cache hit response: <10ms

Network

  • Library API payload: ~1-5MB (depends on metadata richness)
  • Playlist API payload: ~50-200KB
  • Audio streaming: Minimal buffering with range request support
  • Album art: ~50-500KB per image

Cost Analysis

API Usage

Playlist Generation:

  • Input tokens: ~2000-8000 (depends on library size)
  • Output tokens: ~1000-2000
  • Cost per generation: $0.05-0.10
  • Frequency: Once per library change (cached 7 days)

AI Next Song:

  • Input tokens: ~1000-1500 (with sampling)
  • Output tokens: ~50-100
  • Cost per selection: ~$0.004
  • Cache hit rate: 60-75%
  • Effective cost per session (20 tracks): $0.03-0.08

Monthly Estimate:

  • Playlist regeneration: $0.10 (assuming monthly library updates)
  • Daily listening (30 min): $0.03
  • Total: $1-5 per month for typical usage

Technical Implementation Details

JSON Parsing from Claude Responses

Claude API responses occasionally include markdown code blocks wrapping JSON output. The system implements a cleaning function that:

  1. Trims whitespace from response text
  2. Detects markdown code block delimiters (triple backticks)
  3. Extracts content between opening and closing delimiters
  4. Parses cleaned JSON with error handling
  5. Validates expected structure before processing

This approach handles both raw JSON and markdown-wrapped JSON responses without requiring API behavior changes.

Library Hash Calculation

The cache invalidation system uses MD5 hashing of library state:

hash = MD5(file1.path + file1.size + file1.mtime + '|' + file2.path + ...)

This provides fast comparison while detecting:

  • Added files (new paths)
  • Removed files (missing paths)
  • Modified files (changed size or mtime)

The hash is stored with cached playlists and compared on subsequent requests.

Playlist Diversification Algorithm

The fallback algorithm implements a greedy approach to album diversity:

input: tracks[], maxSize
output: diversified[]

shuffle(tracks)
lastAlbum = null
consecutiveCount = 0

for track in tracks:
  if length(diversified) >= maxSize:
    break
  
  if track.album == lastAlbum:
    consecutiveCount++
    if consecutiveCount >= 2:
      continue
  else:
    consecutiveCount = 1
    lastAlbum = track.album
  
  diversified.append(track)

return diversified

This ensures no more than 2 consecutive tracks from the same album while maintaining randomization.

Frontend State Management

The application uses React hooks for state management without external libraries:

Core State:

  • library: Complete music library array
  • currentSong: Currently playing track object
  • isPlaying: Boolean playback state
  • currentTime / duration: Playback position tracking

AI Features State:

  • aiPlaylists: Generated playlists array
  • selectedPlaylist: Active playlist ID
  • aiNextEnabled: AI recommendation toggle
  • recentHistory: Last 10 played tracks
  • nextSongPreloaded: Preloaded next track object
  • hasRequestedNext: Flag to prevent duplicate API calls

Playlist Mode State:

  • currentPlaylistQueue: Active queue with index
  • playlistMode: Boolean queue active state

Notification State:

  • notification: Object containing message, type, and visibility flag

State updates trigger React re-renders which propagate to affected components through props drilling (no context or Redux due to shallow component tree).

Browser Compatibility

Tested and functional on:

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+

Requires:

  • JavaScript ES6+ support
  • CSS Grid and Flexbox
  • Audio element with streaming support
  • Fetch API for network requests

Security Considerations

API Key Protection

The Anthropic API key is stored server-side as an environment variable and never exposed to the client. All AI operations proxy through the Express backend.

File System Access

The server has read-only access to the music directory. No write operations are performed on music files. Cache and playlist data is isolated to /app/data.

Input Validation

User-provided paths in API requests are validated against the mounted music directory to prevent directory traversal attacks. All file operations use path normalization and containment checks.

CORS Configuration

The server implements permissive CORS for development. Production deployments should restrict origins to the frontend domain.

Development Workflow

Local Development

# Server (port 3000)
cd server
npm install
npm run dev

# Client (port 5173)
cd client
npm install
npm run dev

The client dev server proxies API requests to the backend automatically.

Docker Development

docker-compose up --build

Access at http://localhost:8080

Production Build

# Client build
cd client
npm run build

# Server runs in production mode
cd server
npm start

The built client is served by Nginx in the Docker container.

Testing

Backend Testing

cd server
node test-api.js

This script validates Anthropic API key configuration and tests basic playlist generation.

Manual Testing Checklist

  • Library loading and display
  • Album art rendering (embedded and external)
  • Audio playback and seeking
  • Playlist generation (AI and fallback)
  • AI Next Song selection
  • Playlist mode continuity
  • Window dragging functionality
  • View mode switching (list/grid)
  • Genre filtering
  • Playback controls (play, pause, next, previous)

Limitations and Known Issues

Current Limitations

  1. Single-user application (no authentication or multi-user support)
  2. No playlist editing capabilities (generated playlists are read-only)
  3. No mobile-responsive design (desktop-only interface)
  4. No streaming service integration (local files only)
  5. Limited audio format support (no DSD or proprietary formats)

Known Issues

  1. Large libraries (>1000 tracks) may experience slow initial load
  2. Very long playlists (>50 tracks) may cause Claude API timeouts
  3. Album art extraction may fail for some file formats
  4. Window dragging can be jerky on low-end systems

Version History

v1.0.4 (Current)

  • AI Next preloading 20 seconds before track end
  • Toast notification system for AI selections
  • Seamless track transitions with zero-gap playback
  • Preload state management and cleanup

v1.0.3

  • Playlist mode with queue management
  • English playlist names
  • Fix for initial track playback in playlists

v1.0.2

  • JSON parsing fix for markdown-wrapped responses
  • Enhanced error handling

v1.0.1

  • Album diversification in playlist generation
  • Improved variety algorithm

v1.0.0

  • Initial release
  • AI playlist generation
  • AI Next Song feature
  • iTunes-inspired interface

References

Technical Documentation

Design References

  • iTunes 11-12 interface design
  • macOS Human Interface Guidelines
  • Skeuomorphic design principles in pre-iOS 7 Apple software

License

This project is provided as-is for educational and personal use.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages