Files
metadata-agregator/docs/research/meelo/analysis/EVALUATION.md
T
Alexander a1f6701bac feat: initial implementation of metadata aggregator
- gRPC service with MusicBrainz provider
- PostgreSQL schema with migrations
- Service layer with database-first caching
- Repository pattern for data access
- YAML configuration support
- Research documentation for 17 music metadata projects
2026-04-28 16:28:53 +02:00

565 lines
16 KiB
Markdown

# Meelo Evaluation
## Strengths
### Data Model Sophistication
Meelo's data model is the most mature among self-hosted music servers. The Album/Release and Song/Track distinctions accurately represent real-world music organization.
**Album vs Release**:
- Albums are abstract concepts (e.g., "Abbey Road")
- Releases are physical/digital manifestations (original, 2019 remaster, deluxe edition)
- One album can have multiple releases with different track listings, mastering, labels
This mirrors how music collectors think. A remaster is not a different album, it's a different release of the same album.
**Song vs Track**:
- Songs are compositions (e.g., "Come Together")
- Tracks are recordings (studio version, live version, acoustic version)
- One song can have multiple tracks across different releases
This enables tracking different performances of the same composition without creating duplicate songs.
**Song Groups**:
- Group versions of the same composition (original, covers, remixes)
- Example: "Hallelujah" by Leonard Cohen, Jeff Buckley, Pentatonix
- Enables discovering different interpretations
No other self-hosted music server implements this level of versioning.
### Multi-Provider Metadata
Meelo queries 8 external providers:
1. **MusicBrainz**: Primary database, most accurate
2. **Genius**: Lyrics and song descriptions
3. **Wikipedia**: Artist/album context
4. **Wikidata**: Structured data
5. **Discogs**: Release details
6. **AllMusic**: Editorial reviews
7. **Metacritic**: Critic scores
8. **LrcLib**: Synced lyrics
**Aggregation Strategy**:
- Priority-based merging (MusicBrainz > Genius > Wikipedia)
- Concatenate descriptions from multiple sources
- Average ratings across providers
- Prefer synced lyrics over plain
**Result**: Richer metadata than single-provider systems. Descriptions combine MusicBrainz facts, Wikipedia context, and Genius annotations.
### Music Video Support
Videos are first-class citizens, not afterthoughts.
**Video Types**:
- Official music videos
- Live performances
- Lyric videos
- Behind the scenes
- Interviews
- Documentaries
**Integration**:
- Videos link to songs (same as audio tracks)
- Kyoo transcoder handles adaptive streaming
- UI treats videos equally with audio
**Comparison**:
- **Navidrome**: No video support
- **Jellyfin**: Videos are separate media type, not linked to songs
- **Plex**: Similar to Jellyfin
Meelo is the only self-hosted music server with proper music video integration.
### Event-Driven Architecture
RabbitMQ decouples scanning from enrichment.
**Flow**:
1. Scanner registers file with Server
2. Scanner publishes event to RabbitMQ
3. Matcher consumes event asynchronously
4. Matcher queries providers in parallel
5. Matcher pushes enriched metadata to Server
**Benefits**:
- Scanning doesn't block on provider queries
- Matcher can retry failed providers without re-scanning
- Multiple matchers can process events in parallel
- Provider failures don't stop scanning
**Comparison**:
- **Navidrome**: Synchronous metadata fetching blocks scanning
- **Airsonic**: No external metadata providers
### Scrobbling Built-In
Last.fm and ListenBrainz integration is native, not a plugin.
**Features**:
- OAuth flow for Last.fm
- Token-based auth for ListenBrainz
- Automatic scrobbling on track play
- "Now playing" updates
**Comparison**:
- **Navidrome**: Last.fm only, requires external scrobbler
- **Airsonic**: No built-in scrobbling
### Mobile App
Expo/React Native app shares code with web frontend.
**Shared**:
- Components (ArtistCard, AlbumCard, TrackList)
- Hooks (useArtists, useAlbums, usePlayback)
- State management (Jotai atoms)
**Mobile-Specific**:
- React Navigation instead of Next.js router
- AsyncStorage instead of localStorage
- expo-av for media playback
- expo-notifications for background playback
**Result**: Feature parity between web and mobile without duplicating code.
**Comparison**:
- **Navidrome**: Third-party mobile apps (Substreamer, Subtracks)
- **Jellyfin**: Official mobile app, but music is secondary
### Search Performance
MeiliSearch provides sub-100ms search across large libraries.
**Features**:
- Typo tolerance (handles misspellings)
- Faceted search (filter by genre, year, type)
- Instant results (as-you-type)
- Relevance ranking
**Indexed Entities**:
- Artists (name, sort name)
- Albums (name, artist name, type, release date)
- Songs (name, artist name, type)
- Videos (name, artist name, type)
**Comparison**:
- **Navidrome**: Database full-text search (slower, no typo tolerance)
- **Airsonic**: Basic SQL LIKE queries
### Active Development
**Indicators**:
- 40 releases (consistent iteration)
- 1,095 stars (healthy community)
- GitHub Actions CI/CD per service
- SonarCloud quality gates
- Regular commits (weekly)
**Comparison**:
- **Navidrome**: Active (single maintainer)
- **Airsonic**: Stagnant (last release 2020)
- **Funkwhale**: Active but slower
### Geographic Context
Areas (countries, cities, regions) are first-class entities.
**Features**:
- ISO 3166 codes
- Parent/child hierarchy (city → state → country)
- Artist associations (birthplace, formation location)
**Use Case**:
- Browse artists by location
- Discover local music scenes
- Understand artist context
**Comparison**: No other self-hosted music server has area support.
### Code Quality
**Measures**:
- SonarCloud enforces 80% coverage, no critical bugs
- Biome linting for TypeScript
- Pyright type checking for Python
- golangci-lint for Go
- Jest, pytest, Go testing
**Result**: High code quality, low bug rate.
## Weaknesses
### Complex Deployment
8+ containers required:
1. Server (NestJS)
2. Scanner (Go)
3. Matcher (Python)
4. Front (Next.js)
5. PostgreSQL
6. MeiliSearch
7. RabbitMQ
8. Kyoo Transcoder
9. Nginx
**Challenges**:
- Docker Compose orchestration
- Health check dependencies
- Volume management
- Network configuration
- Resource allocation
**Comparison**:
- **Navidrome**: Single binary, no dependencies
- **Airsonic**: Single JAR, embedded database option
**Impact**: High barrier to entry for non-technical users.
### Multi-Language Stack
4 languages across services:
- TypeScript (Server, Front)
- Go (Scanner)
- Python (Matcher)
- TypeScript again (Front mobile)
**Challenges**:
- Different toolchains (npm, go, pip)
- Different testing frameworks (Jest, Go testing, pytest)
- Different linting tools (Biome, golangci-lint, Ruff)
- Harder to contribute (need expertise in multiple languages)
**Comparison**:
- **Navidrome**: Single language (Go)
- **Airsonic**: Single language (Java)
**Impact**: Steeper learning curve for contributors.
### Heavy Infrastructure
Required services:
- **PostgreSQL**: Relational database
- **MeiliSearch**: Search engine
- **RabbitMQ**: Message queue
- **Kyoo Transcoder**: Video transcoding
**Resource Requirements**:
- Minimum: 4GB RAM, 2 CPU cores
- Recommended: 8GB RAM, 4 CPU cores
- Storage: 10GB + library size
**Comparison**:
- **Navidrome**: 512MB RAM, 1 CPU core, SQLite
- **Airsonic**: 1GB RAM, 1 CPU core, embedded database
**Impact**: Not suitable for low-power devices (Raspberry Pi 3, old NAS).
### Requires Clean Collection
Meelo works best with well-organized music:
- Embedded metadata (ID3 tags, Vorbis comments)
- Standard folder structure (Artist/Album/Track)
- Consistent naming
**Challenges**:
- Messy collections require manual cleanup
- Missing tags need filename regex
- Inconsistent naming breaks matching
**Comparison**:
- **Navidrome**: More forgiving, uses folder structure
- **Jellyfin**: Handles messy collections better
**Impact**: Not suitable for users with poorly organized libraries.
### GPL-3.0 License
**Restrictions**:
- Derivative works must be GPL-3.0
- Source code must be disclosed
- No proprietary forks
**Impact**:
- Prevents commercial SaaS offerings
- Limits corporate adoption
- Acceptable for self-hosters, restrictive for businesses
**Comparison**:
- **Navidrome**: GPL-3.0 (same restrictions)
- **Jellyfin**: GPL-2.0 (similar restrictions)
- **Airsonic**: GPL-3.0 (same restrictions)
### Kyoo Transcoder Dependency
Video transcoding relies on external project (Kyoo).
**Risks**:
- Kyoo development stalls
- Breaking changes in Kyoo API
- Meelo must maintain compatibility
**Comparison**:
- **Jellyfin**: Built-in transcoder (FFmpeg wrapper)
- **Plex**: Built-in transcoder
**Impact**: Video support is fragile.
### No Prometheus Metrics
No built-in metrics for monitoring.
**Missing**:
- Request rates
- Error rates
- Latency percentiles
- Queue depths
- Provider response times
**Workaround**: Parse logs or use external monitoring.
**Comparison**:
- **Navidrome**: Prometheus metrics endpoint
- **Jellyfin**: No metrics
**Impact**: Harder to monitor in production.
## Integration Potential
### Data Model
**Applicability**: Excellent reference for metadata aggregator.
**Lessons**:
- Separate abstract entities (Album, Song) from concrete instances (Release, Track)
- Use song groups for versioning
- Store external metadata separately from core entities
- Use local identifiers for cross-referencing
**Adoption**:
- Implement Album/Release distinction
- Implement Song/Track distinction
- Implement song groups for covers/remixes
- Separate ExternalMetadata table
### Provider Pattern
**Applicability**: Directly applicable to metadata aggregator.
**Architecture**:
- Base provider interface (search, fetch)
- Per-provider modules (musicbrainz.py, genius.py)
- Factory pattern for provider instantiation
- Parallel queries with asyncio
- Rate limiting per provider
- Priority-based aggregation
**Adoption**:
- Copy provider interface design
- Implement factory pattern
- Use asyncio for parallel queries
- Implement per-provider rate limiters
- Use priority-based merging
### Event-Driven Enrichment
**Applicability**: Scalable approach for metadata aggregator.
**Architecture**:
- Scanner publishes events to queue
- Matcher consumes events asynchronously
- Server receives enriched metadata via API
- Decouples scanning from enrichment
**Adoption**:
- Use message queue (RabbitMQ, Redis Streams)
- Separate scanner and matcher services
- Enable retries without re-scanning
### Search Integration
**Applicability**: Fast search is critical for metadata aggregator.
**Architecture**:
- MeiliSearch for full-text search
- Index on entity creation/update
- Typo tolerance and faceted search
- Sub-100ms response times
**Adoption**:
- Integrate MeiliSearch or Typesense
- Index artists, albums, songs
- Implement as-you-type search
## Relevance to Metadata Aggregator
### High Relevance
**Data Model**:
- Album/Release and Song/Track distinctions are essential for accurate metadata
- Song groups enable tracking versions and covers
- External metadata separation keeps provider data clean
**Provider Architecture**:
- Factory pattern simplifies adding new providers
- Parallel queries optimize performance
- Rate limiting prevents API bans
- Priority-based aggregation ensures quality
**Event-Driven Design**:
- Decouples metadata fetching from file scanning
- Enables retries without re-processing
- Scales horizontally (multiple matchers)
### Medium Relevance
**Search Integration**:
- Fast search improves user experience
- Typo tolerance handles misspellings
- Faceted search enables filtering
**Scrobbling**:
- OAuth flows are reusable patterns
- Token management is standard practice
**Mobile App**:
- Code sharing between web and mobile reduces duplication
- Monorepo structure simplifies version coordination
### Low Relevance
**Video Support**:
- Metadata aggregator may not handle videos
- Transcoding is out of scope
**Geographic Context**:
- Areas are nice-to-have, not essential
- ISO 3166 codes are useful for standardization
**Deployment Complexity**:
- Metadata aggregator may use simpler deployment (single service)
- Docker Compose is overkill for smaller projects
## Comparison with Alternatives
### vs Navidrome
**Meelo Advantages**:
- Richer data model (Album/Release, Song/Track)
- Multi-provider metadata (8 vs 1)
- Music video support
- Built-in scrobbling
- Search performance (MeiliSearch vs SQL)
**Navidrome Advantages**:
- Simpler deployment (single binary)
- Lower resource requirements (512MB vs 4GB)
- Faster startup (no dependencies)
- More mature (older project)
**Verdict**: Meelo for metadata richness, Navidrome for simplicity.
### vs Jellyfin
**Meelo Advantages**:
- Music-focused (not general media server)
- Better music metadata (Album/Release, Song/Track)
- Multi-provider enrichment
- Faster search (MeiliSearch)
**Jellyfin Advantages**:
- Handles all media types (movies, TV, music)
- Larger community
- More mature
- Better transcoding (built-in)
**Verdict**: Meelo for music collectors, Jellyfin for general media.
### vs Airsonic
**Meelo Advantages**:
- Modern stack (NestJS, Next.js vs Java)
- Active development (40 releases vs stagnant)
- Better metadata (multi-provider)
- Search performance
**Airsonic Advantages**:
- Simpler deployment (single JAR)
- Subsonic API compatibility
- Larger ecosystem (mobile apps)
**Verdict**: Meelo for modern features, Airsonic for stability.
### vs Funkwhale
**Meelo Advantages**:
- Better metadata model
- Multi-provider enrichment
- Faster search
**Funkwhale Advantages**:
- Federated (share music across instances)
- Social features (follows, favorites)
- Podcast support
**Verdict**: Meelo for personal use, Funkwhale for communities.
## Recommendations for Metadata Aggregator
### Adopt
1. **Data Model**:
- Implement Album/Release distinction
- Implement Song/Track distinction
- Implement song groups for versions
- Separate ExternalMetadata table
2. **Provider Pattern**:
- Base provider interface
- Per-provider modules
- Factory pattern
- Parallel queries with asyncio
- Rate limiting per provider
- Priority-based aggregation
3. **Event-Driven Architecture**:
- Message queue for decoupling
- Separate scanner and matcher services
- Retry logic without re-scanning
### Adapt
1. **Search Integration**:
- Use MeiliSearch or Typesense
- Index on entity creation/update
- Implement typo tolerance
2. **Scrobbling**:
- OAuth flows for Last.fm
- Token-based auth for ListenBrainz
3. **Code Quality**:
- Linting (Biome, Ruff)
- Type checking (TypeScript, Pyright)
- Testing (Jest, pytest)
- SonarCloud quality gates
### Avoid
1. **Complex Deployment**:
- Prefer single service or fewer containers
- Avoid heavy infrastructure (PostgreSQL, RabbitMQ) if possible
- Use SQLite for smaller deployments
2. **Multi-Language Stack**:
- Stick to one or two languages
- Avoid mixing TypeScript, Go, Python unless necessary
3. **Kyoo Dependency**:
- If video support needed, use built-in transcoder (FFmpeg)
- Avoid external dependencies for core features
## Summary
Meelo excels at data modeling, multi-provider metadata enrichment, and music video support. The Album/Release and Song/Track distinctions are the most accurate representation of real-world music organization among self-hosted servers. The provider pattern with parallel queries and priority-based aggregation is directly applicable to metadata aggregators. The event-driven architecture scales well and decouples concerns. However, deployment complexity (8+ containers), multi-language stack (TypeScript, Go, Python), and heavy infrastructure (PostgreSQL, MeiliSearch, RabbitMQ) limit accessibility. The GPL-3.0 license restricts commercial use. For a metadata aggregator, adopt the data model and provider architecture, adapt the search integration and scrobbling patterns, but avoid the deployment complexity and multi-language stack. Meelo is an excellent reference for sophisticated metadata handling in a self-hosted context.