- Full PWA support with offline capabilities - Comprehensive search across songs, playlists, and channels - Offline playlist manager with download tracking - Pre-built frontend for zero-build deployment - Docker-based deployment with docker compose - Material-UI dark theme interface - YouTube audio download and management - Multi-user authentication support
9.4 KiB
SoundWave - ID3 Tags and Artwork Feature Implementation Summary
Overview
Implemented comprehensive ID3 tagging and artwork management system with support for Last.fm and Fanart.tv APIs.
What Was Implemented
1. Dependencies Added
File: requirements.txt
mutagen>=1.47.0- ID3 tag reading/writing for MP4/M4A, MP3, FLACpylast>=5.2.0- Last.fm API client
2. Database Models
File: audio/models_artwork.py
Artwork Model
- Stores artwork with multiple types (thumbnail, cover, album, artist image/banner/logo)
- Supports multiple sources (YouTube, Last.fm, Fanart.tv, manual)
- Tracks URL, local path, dimensions, priority
- Can be linked to Audio or Channel
MusicMetadata Model
- OneToOne relationship with Audio
- Stores album info, track/disc numbers, genre, tags
- Includes Last.fm data (URL, MBID, play count, listeners)
- Fanart.tv IDs for artwork lookup
ArtistInfo Model
- OneToOne relationship with Channel
- Stores artist bio, Last.fm statistics
- Tags, similar artists
- MusicBrainz and Fanart.tv IDs
3. ID3 Service
File: audio/id3_service.py
ID3TagService Class
Methods:
read_tags(file_path)- Read tags from audio fileswrite_tags(file_path, tags)- Write tags to audio filesembed_cover_art(file_path, image_data, mime_type)- Embed cover artextract_cover_art(file_path)- Extract embedded cover art
Supported formats (broad codec support):
Lossy formats:
- MP3 (ID3v2)
- MP4/M4A/M4B/M4P (iTunes)
- OGG Vorbis
- Opus
- Musepack (.mpc)
Lossless formats:
- FLAC
- WavPack (.wv)
- Monkey's Audio (.ape)
- AIFF/AIF/AIFC
- WAV
High-resolution DSD:
- DSF (DSD Stream File)
- DFF (DSDIFF)
Supported tags:
- title, artist, album, album_artist
- year, genre
- track_number, disc_number
- duration, bitrate (read-only)
- sample_rate, channels, bits_per_sample (DSD formats)
4. Last.fm API Client
File: audio/lastfm_client.py
LastFMClient Class
Methods:
search_track(artist, title)- Search for track with metadata and artworkget_artist_info(artist_name)- Get artist bio, stats, tags, similar artistsget_album_info(artist, album)- Get album metadata and cover artdownload_image(url, output_path)- Download artwork to local file
Features:
- Automatic MusicBrainz ID retrieval
- Multiple image size support
- Play count and listener statistics
- Tag and genre extraction
5. Fanart.tv API Client
File: audio/fanart_client.py
FanartClient Class
Methods:
get_artist_images(musicbrainz_id)- Get all artist artwork by typeget_album_images(musicbrainz_release_id)- Get album covers and disc artget_best_artist_image(musicbrainz_id, image_type)- Get highest-rated imageget_best_album_cover(musicbrainz_release_id)- Get highest-rated coversearch_by_artist_name(artist_name)- Find MusicBrainz IDdownload_image(url, output_path)- Download artwork
Artwork types:
- Artist: backgrounds, thumbnails, logos, HD logos, banners
- Album: covers, disc art
Features:
- Like-based sorting
- Multiple image sizes
- MusicBrainz integration
6. Celery Tasks
File: audio/tasks_artwork.py
Background Tasks
fetch_metadata_for_audio(audio_id)- Fetch Last.fm metadatafetch_artwork_for_audio(audio_id)- Fetch artwork from all sourcesfetch_artist_info(channel_id)- Fetch artist bio and statsfetch_artist_artwork(channel_id)- Fetch artist images/banners/logosdownload_artwork(artwork_id)- Download artwork from URL to local storageembed_artwork_in_audio(audio_id, artwork_id)- Embed cover art in audio fileupdate_id3_tags_from_metadata(audio_id)- Write metadata to audio file tags
Batch Tasks
auto_fetch_artwork_batch(limit)- Auto-fetch for audio without artworkauto_fetch_artist_info_batch(limit)- Auto-fetch for channels without info
All tasks:
- Max 3 retries with 5-minute delays
- Proper error handling and logging
- Idempotent (safe to run multiple times)
7. API Endpoints
Files: audio/views_artwork.py, audio/serializers_artwork.py, audio/urls_artwork.py
ViewSets
-
ArtworkViewSet - CRUD operations for artwork
- List, create, update, delete
- Filter by audio_id, channel_id, type, source
- Actions:
download,set_primary
-
MusicMetadataViewSet - Metadata management
- CRUD operations
- Actions:
fetch_from_lastfm,update_id3_tags
-
ArtistInfoViewSet - Artist information management
- CRUD operations
- Action:
fetch_from_lastfm
-
AudioArtworkViewSet - Audio artwork operations
retrieve- Get all artwork for audio- Actions:
fetch_artwork,fetch_metadata,embed_artwork
-
ChannelArtworkViewSet - Channel artwork operations
retrieve- Get all artwork for channel- Actions:
fetch_artwork,fetch_info
URL Patterns
/api/audio/api/artwork/
/api/audio/api/metadata/
/api/audio/api/artist-info/
/api/audio/api/audio-artwork/{id}/
/api/audio/api/channel-artwork/{id}/
8. Django Admin
File: audio/admin_artwork.py
Admin Classes
-
ArtworkAdmin
- List display: audio, channel, type, source, priority, primary flag
- Filters: type, source, primary, date
- Actions: download_artwork, set_as_primary
-
MusicMetadataAdmin
- List display: audio, album, artist, genre, year, stats
- Actions: fetch_from_lastfm, update_id3_tags
-
ArtistInfoAdmin
- List display: channel, listeners, playcount, bio status, tags count
- Action: fetch_from_lastfm
9. Configuration
Files: config/settings.py, .env.example, config/celery.py
Settings Added
LASTFM_API_KEY = os.environ.get('LASTFM_API_KEY', '')
LASTFM_API_SECRET = os.environ.get('LASTFM_API_SECRET', '')
FANART_API_KEY = os.environ.get('FANART_API_KEY', '')
Celery Beat Schedule
auto-fetch-artwork- Every 2 hours (50 tracks)auto-fetch-artist-info- Daily at 2 AM (20 channels)
10. Documentation
File: audio/README_ARTWORK.md
- Complete feature documentation
- API reference
- Usage examples
- Setup instructions
- Troubleshooting guide
File Structure
backend/
├── requirements.txt (updated)
├── config/
│ ├── settings.py (updated)
│ └── celery.py (updated)
└── audio/
├── models_artwork.py (new)
├── id3_service.py (new)
├── lastfm_client.py (new)
├── fanart_client.py (new)
├── tasks_artwork.py (new)
├── views_artwork.py (new)
├── serializers_artwork.py (new)
├── urls_artwork.py (new)
├── admin_artwork.py (new)
├── urls.py (updated)
└── README_ARTWORK.md (new)
API Key Setup Required
Last.fm API
- Register at: https://www.last.fm/api/account/create
- Add to
.env:LASTFM_API_KEY=your_api_key LASTFM_API_SECRET=your_api_secret
Fanart.tv API
- Register at: https://fanart.tv/get-an-api-key/
- Add to
.env:FANART_API_KEY=your_api_key
Next Steps
To Deploy:
-
Install dependencies:
pip install -r requirements.txt -
Run migrations:
python manage.py makemigrations audio python manage.py migrate -
Configure API keys in
.env -
Restart services:
docker-compose restart soundwave soundwave-worker
To Test:
- Upload audio track
- Trigger artwork fetch:
POST /api/audio/api/audio-artwork/{audio_id}/fetch_artwork/ - Check artwork in Django admin
- View embedded artwork in audio file
Features Summary
✅ Broad Codec Support - Read/write tags for 15+ audio formats including DSD (DSF, DFF) ✅ ID3 Tag Support - MP3, MP4, FLAC, OGG, Opus, WavPack, APE, Musepack, AIFF, WAV ✅ High-Resolution Audio - Full DSD support (DSF, DSDIFF) with sample rate detection ✅ Last.fm Integration - Metadata, artwork, artist info, similar artists ✅ Fanart.tv Integration - High-quality artwork (images, banners, logos) ✅ Automatic Artwork Fetching - Background tasks with Celery ✅ Multiple Artwork Sources - YouTube, Last.fm, Fanart.tv, manual ✅ Priority-Based Selection - Best artwork chosen automatically ✅ Cover Art Embedding - Embed artwork in all supported audio formats ✅ Local Artwork Caching - Reduce API calls ✅ RESTful API - Complete CRUD operations ✅ Django Admin Interface - Easy management ✅ Comprehensive Documentation - README with examples
Technical Highlights
- Asynchronous Processing - All API calls via Celery tasks
- Broad Format Support - 15+ audio formats: MP3, MP4, FLAC, OGG, Opus, WavPack, APE, Musepack, DSF, DFF, AIFF, WAV
- DSD Audio Support - Native support for high-resolution DSD formats (DSF, DSDIFF)
- External API Integration - Last.fm and Fanart.tv
- Automatic Scheduling - Periodic background tasks
- Robust Error Handling - Retry logic and logging
- Extensible Architecture - Easy to add more sources
- Database Optimization - Efficient queries with prefetch
- REST API Design - Standard patterns with DRF
- Format-Specific Handlers - ID3v2 for MP3/DSF/DFF, MP4 tags, Vorbis comments, APEv2
Notes
- API keys are optional - system works without them (uses YouTube thumbnails only)
- Last.fm provides good metadata and basic artwork
- Fanart.tv requires MusicBrainz IDs but provides highest quality artwork
- All artwork is cached locally to reduce API usage
- Priority system ensures best artwork is always used
- ID3 tags can be updated manually or automatically from metadata