Files
swingmusic-extended/music_services_analysis.md
T
Tomas Dvorak cbf646e25b Fix CI/CD pipeline and code quality issues
## Major Changes
- Fixed all TypeScript errors in web client for successful compilation
- Resolved 82+ Python lint errors across backend services
- Updated Flutter SDK compatibility for mobile app
- Fixed security workflow configuration

## Web Client Fixes
- Fixed import path in DragonflyDashboard.vue (dragonflyApi import)
- All TypeScript compilation now passes without errors

## Backend Lint Fixes
- Updated type annotations to modern Python syntax (dict instead of Dict, X | None instead of Optional[X])
- Replaced try-except-pass with contextlib.suppress(Exception)
- Removed unused imports (Dict, Optional, Any, Iterator, etc.)
- Fixed bare except clauses to use Exception
- Sorted and formatted imports with ruff
- Applied ruff format to 27 files

## Workflow Fixes
- Updated Flutter SDK constraint from ^3.10.4 to ^3.5.0 (compatible with Flutter 3.24.0)
- Changed pip-audit format from github to json in security.yml
- Added comprehensive CI workflows (readiness-gate.yml, security.yml)

## Infrastructure
- Added DragonflyDB caching system integration
- Enhanced Docker configuration with multi-stage builds
- Added pytest configuration and test infrastructure
- Improved production readiness with proper error handling

## Verification
- backend-lint job:  Succeeded
- web job:  Succeeded
- Ready for GitHub deployment

All CI/CD issues resolved. Codebase now passes all quality checks.
2026-03-21 10:01:14 +01:00

195 lines
5.8 KiB
Markdown

# Music Services Architecture Analysis
## Current Services Overview
### 🎵 **Spotify (Web Player API) - PRIMARY METADATA SOURCE**
**Purpose**: Core track, album, artist, playlist metadata
**Status**: ✅ Working - No account required
**Used for**:
- Track names, artists, albums, durations
- Playlist information and track listings
- Artist discography and top tracks
- Album details and tracklists
- Preview URLs (when available)
**Implementation**: SpotiFLAC-style Web Player API
- TOTP authentication (no account needed)
- GraphQL persisted queries
- Client token requirement
- Rate limiting with retries
---
### 🎼 **MusicBrainz - ENRICHMENT METADATA**
**Purpose**: Comprehensive music database enrichment
**Status**: ✅ Working - Free API
**Used for**:
- **Genre information** (primary use case)
- **ISRC codes** for cross-platform matching
- **Release dates and detailed discography**
- **Artist relationships and aliases**
- **Cover art URLs** (via Cover Art Archive)
- **Track positioning and numbering**
- **Country-specific release information**
- **User-generated tags and ratings**
**Key Benefits**:
- **Free and open** (no API keys needed)
- **Comprehensive database** with 1.5M+ artists
- **Genre data** that Spotify doesn't provide
- **ISRC codes** for streaming service matching
---
### 📻 **Last.fm - SOCIAL & LISTENING DATA**
**Purpose**: Social music features and listening statistics
**Status**: ⚠️ Optional - Requires user API key
**Used for**:
- **Scrobbling** (track what users listen to)
- **Play counts** and listening statistics
- **User recommendations** and similar artists
- **Social features** (friends, groups)
- **Charts** and trending data
- **Personalized recommendations**
**Current Issues**:
- Requires user API key and authentication
- Optional dependency (can be disabled)
- Used mainly for social features
---
## 🎯 **Optimal Architecture Recommendation**
### **Core Required Services**
1. **Spotify Web Player API** (Primary metadata)
2. **MusicBrainz** (Genre enrichment + ISRC matching)
### **Optional Services**
3. **Song.link** (Cross-platform streaming URLs)
4. **Last.fm** (Social features - can be disabled)
---
## 💡 **Your Question: Listening Count Implementation**
You're absolutely right! Here's how we can handle listening counts:
### **Option 1: Use Spotify Data (Recommended)**
```python
# Spotify provides playcount in Web Player API
track_data = {
"playcount": 1234567, # Real Spotify play count
"popularity": 85, # Spotify popularity score
}
```
**Pros**:
- Real-time data from Spotify
- No additional API calls needed
- Accurate and up-to-date
**Cons**:
- Depends on Spotify API availability
### **Option 2: Use MusicBrainz Data**
```python
# MusicBrainz has rating and tag data
mb_data = {
"rating": 4.2, # User rating (0-5)
"tagList": ["rock", "popular"], # User tags
"playCount": None, # Not directly available
}
```
**Pros**:
- Free and always available
- Community-driven data
- Genre information included
**Cons**:
- No direct play count
- Less accurate for popularity
### **Option 3: Local Tracking (Hybrid Approach)**
```python
# Track local plays in database + enrich with external data
local_stats = {
"localPlayCount": 156, # Times played in SwingMusic
"spotifyPlayCount": 1234567, # From Spotify API
"lastfmPlayCount": 98765, # From Last.fm (if available)
}
```
---
## 🚀 **Recommended Implementation**
### **Required Services (Always On)**
```python
class UnifiedMetadataClient:
def __init__(self):
self.spotify = SpotifyWebPlayerClient() # Primary metadata
self.musicbrainz = MusicBrainzClient() # Genre enrichment
self.songlink = SongLinkClient() # Cross-platform URLs
def get_track(self, track_id):
# Get core data from Spotify
spotify_data = self.spotify.get_track(track_id)
# Enrich with MusicBrainz genre data
if spotify_data.isrc:
mb_data = self.musicbrainz.get_by_isrc(spotify_data.isrc)
spotify_data.genres = mb_data.genres
# Get cross-platform URLs
cross_platform = self.songlink.get_links(track_id)
spotify_data.streaming_urls = cross_platform
return spotify_data
```
### **Optional Services (User Configurable)**
```python
class OptionalFeatures:
def __init__(self):
self.lastfm_enabled = user_config.get("lastfm_enabled", False)
self.lastfm = LastFmClient() if self.lastfm_enabled else None
def get_play_counts(self, track_id):
counts = {
"spotify": self.spotify.get_playcount(track_id),
"local": self.local_db.get_playcount(track_id),
}
if self.lastfm_enabled:
counts["lastfm"] = self.lastfm.get_playcount(track_id)
return counts
```
---
## 📊 **Summary Table**
| Service | Purpose | Required? | Data Provided |
|---------|---------|-----------|---------------|
| **Spotify** | Core metadata | ✅ Yes | Names, artists, albums, durations, play counts |
| **MusicBrainz** | Genre enrichment | ✅ Yes | Genres, ISRC, cover art, release info |
| **Song.link** | Cross-platform URLs | ✅ Yes | Tidal, Qobuz, Amazon, Deezer links |
| **Last.fm** | Social features | ⚠️ Optional | Scrobbles, social stats, recommendations |
---
## 🎯 **Final Recommendation**
**Keep Last.fm optional** as you suggested. Use **Spotify play counts** as the primary listening count source, with **local tracking** as backup. This gives you:
1. **Real Spotify data** (most accurate)
2. **Local statistics** (always available)
3. **Optional social features** (user choice)
4. **Genre enrichment** (from MusicBrainz)
5. **Cross-platform matching** (from Song.link)
This architecture is **robust, free, and user-controllable**! 🎉