The Problem
Building a local music library from streaming service links is fragmented: each service has its own URL scheme, metadata quality, and download method. Users end up with untagged files, messy folder structures, and no way to get a coherent, media-server-ready collection. Antra solves this by turning links from Spotify, YouTube Music, Apple Music, Amazon Music, Tidal, Qobuz, and Deezer into a fully tagged local library in FLAC, ALAC, AAC, or MP3.
What This Does
Antra is a desktop application with a Python backend (antra/) and a Wails-based GUI (antra-wails/). It fetches track metadata, downloads audio, tags files with title, artist, album, artwork, genre, and lyrics, then files them into an Artist / Album structure ready for Navidrome, Jellyfin, or Plex.
The core logic lives in antra/core/ — service.py orchestrates sources, engine.py handles downloads and errors, and resolver.py tracks source success. Each streaming service has a fetcher in antra/sources/ (e.g., amazon.py, apple.py, tidal.py). The GUI layer in antra-wails/ wraps the Python backend via Go bindings.
How It Is Wired
Execution starts at main in antra/__main__.py:502, which reaches 400 functions. From there, run (line 685) dispatches to either process_library_mode or process_resources. The shortest path to an external effect is main -> cleanup_project_junk (filesystem via shutil.rmtree), and process_resources -> fetch_playlist_tracks -> _fetch_spotfetch_tracks (network via SpotFetchFetcher).
The most-connected module is antra/core/models.py — 36 modules import it, making it the highest-blast-radius file. antra/core/service.py is the hub for orchestration (58 functions, 31 imports), while antra/sources/amazon.py is the most complex source (42 functions, calls out to network, filesystem, and subprocesses). The call graph shows search is called from 58 places, TrackMetadata from 30, and resolve from 16 — changing these ripples widely.
The module graph has no circular dependencies, which keeps refactoring tractable. antra/core/models.py is a stable hub (instability 0), while antra/core/service.py (0.94) and antra/core/engine.py (0.93) are highly unstable — they depend on everything else, so changes to them are low-risk but changes to their dependencies are not.
How To Use It
- Setup: Clone with
git clone https://github.com/moses-y/Antra. The repo hasrequirements-desktop.txtandrequirements-runtime.txtfor Python, andantra-wails/go.modfor the Go backend. - Configuration:
.env.exampleshows required env vars. The GUI is configured viaantra-wails/wails.json. - Running it: The Python CLI entry point is
python -m antra. The desktop app builds viabuild_desktop.py(Wails). No Dockerfile or Makefile exists, so build commands are not documented in-repo.
Real-World Use
A user pastes a Spotify playlist link into the GUI. The backend resolves the URL via antra/core/spotify.py, fetches track metadata, downloads audio, tags it with antra/utils/tagger.py, and files it into Artist/Album/ via antra/utils/organizer.py. The result is a media-server-ready library without manual tagging.
Code Health & Issues
Static analysis found 100 issues (29 high, 71 medium) across 6 kinds. Key findings:
- High - No test suite: 90 source files, zero test files. Any change ships with no regression signal.
- High - Unpinned GitHub Actions:
.github/workflowsusessoftprops/action-gh-release@v2— a tag can be moved, risking token exposure. - Med - Broad exception handling: 24 instances of bare
exceptinantra/utils/runtime.py,antra/core/config.py, andantra/core/amazon_music_fetcher.py. - Med - Deep nesting: 24 files with max indentation depth 10, notably
antra/core/apple_fetcher.pyandantra/core/spotify.py. - Med - No dependency scan or Dependabot in CI.
- Med - Duplicated code: 190 repeated 6-line blocks across 30 files.
- Low - No job timeouts in CI, missing
.editorconfigand.gitattributes.
The Bottom Line
Antra is a functional, well-structured music library builder with a solid module layout and no circular dependencies. The lack of tests and unpinned CI actions are the main risks for anyone maintaining it. It is useful for users who want a self-hosted, tagged library from streaming links; engineers should add tests and pin CI before relying on it.