- 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
16 KiB
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:
- MusicBrainz: Primary database, most accurate
- Genius: Lyrics and song descriptions
- Wikipedia: Artist/album context
- Wikidata: Structured data
- Discogs: Release details
- AllMusic: Editorial reviews
- Metacritic: Critic scores
- 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:
- Scanner registers file with Server
- Scanner publishes event to RabbitMQ
- Matcher consumes event asynchronously
- Matcher queries providers in parallel
- 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:
- Server (NestJS)
- Scanner (Go)
- Matcher (Python)
- Front (Next.js)
- PostgreSQL
- MeiliSearch
- RabbitMQ
- Kyoo Transcoder
- 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
-
Data Model:
- Implement Album/Release distinction
- Implement Song/Track distinction
- Implement song groups for versions
- Separate ExternalMetadata table
-
Provider Pattern:
- Base provider interface
- Per-provider modules
- Factory pattern
- Parallel queries with asyncio
- Rate limiting per provider
- Priority-based aggregation
-
Event-Driven Architecture:
- Message queue for decoupling
- Separate scanner and matcher services
- Retry logic without re-scanning
Adapt
-
Search Integration:
- Use MeiliSearch or Typesense
- Index on entity creation/update
- Implement typo tolerance
-
Scrobbling:
- OAuth flows for Last.fm
- Token-based auth for ListenBrainz
-
Code Quality:
- Linting (Biome, Ruff)
- Type checking (TypeScript, Pyright)
- Testing (Jest, pytest)
- SonarCloud quality gates
Avoid
-
Complex Deployment:
- Prefer single service or fewer containers
- Avoid heavy infrastructure (PostgreSQL, RabbitMQ) if possible
- Use SQLite for smaller deployments
-
Multi-Language Stack:
- Stick to one or two languages
- Avoid mixing TypeScript, Go, Python unless necessary
-
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.