How the SpotifySaver CLI Explain Mode Shows Score Breakdown Without Downloading Tracks
The SpotifySaver CLI uses the --explain flag to perform a dry-run analysis that searches YouTube Music candidates and displays detailed scoring components for each potential match without executing any download logic or writing files to disk.
The gabrielbaute/spotify-saver repository provides a Python-based command-line tool for converting Spotify tracks to local audio files via YouTube Music sources. When matches seem incorrect or users want to audit the selection algorithm, the explain mode offers a transparent view of the scoring mechanism. This feature leverages the ScoreMatchCalculator class to expose how duration, artist overlap, title similarity, and album metadata contribute to the final match score while completely bypassing file I/O operations.
How the Explain Mode Works
Explain mode operates as a search-only diagnostic tool that intercepts the standard download flow before any audio retrieval or file writing occurs.
CLI Flag Declaration and Propagation
The entry point for this functionality begins in the download command definition. In spotifysaver/cli/commands/download/download.py, the CLI declares the boolean flag:
@click.option("--explain", is_flag=True,
help="Show score breakdown for each track without downloading (for error analysis)")
When users invoke the command with this flag, the parameter propagates through the processing hierarchy. Whether handling a single track, album, or playlist, the explain boolean passes down to the respective process_* functions, ultimately reaching process_track in spotifysaver/cli/commands/download/track.py.
Candidate Retrieval and Scoring
Upon entering explain mode, the application switches from the standard "select-best-and-download" flow to a diagnostic display. The process_track function instantiates a ScoreMatchCalculator and calls searcher.search_raw(track), which returns all raw candidate results from YouTube Music rather than a single best match.
For each candidate result, the CLI invokes:
explanation = scorer.explain_score(result, track, strict=True)
This method, implemented in spotifysaver/services/score_match_calculator.py, computes individual component scores including duration similarity, artist overlap, title similarity, and album bonus. The method returns a dictionary containing these discrete values plus the aggregated total score.
Human-Readable Output and Early Exit
The CLI renders the score breakdown in a structured format:
- Candidate: <yt_title>
Video ID: <yt_videoId>
Duration: <duration_score>
Artist: <artist_score>
Title: <title_score>
Album: <album_bonus>
→ Total: <total_score> (passed: <passed>)
After displaying all candidates, the code identifies the best match using:
best = max(results, key=lambda r: scorer.explain_score(r, track)["total_score"])
Crucially, the function returns immediately after printing these explanations, bypassing the downloader.download_track_cli call and all file-writing operations. This early exit at lines 65-66 of track.py ensures zero bytes are written to disk and no audio streams are fetched.
Running Explain Mode from the Command Line
To analyze a specific Spotify track's matching logic, execute:
spotify-saver download https://open.spotify.com/track/5K4W6fqB6G1e6pX5K6Zp8Y --explain
The output displays each YouTube candidate with component scores:
🔍 Explaining matches for track: Never Gonna Give You Up
🎵 Track: Never Gonna Give You Up
- Candidate: Rick Astley – Never Gonna Give You Up (Official Music Video)
Video ID: dQw4w9WgXcQ
Duration: 0.3
Artist: 0.3
Title: 0.28
Album: 0.1
→ Total: 0.98 (passed: True)
----------------------------------------
✅ Best candidate: Rick Astley – Never Gonna Give You Up (Official Music Video) (score: 0.98)
The command terminates after displaying the analysis without creating any audio files or metadata directories.
Implementing Explain Logic in Custom Scripts
Developers can replicate this analysis programmatically without invoking the CLI:
from spotifysaver.services import YoutubeMusicSearcher, ScoreMatchCalculator
from spotifysaver.services import SpotifyAPI
spotify = SpotifyAPI()
searcher = YoutubeMusicSearcher()
track = spotify.get_track("https://open.spotify.com/track/5K4W6fqB6G1e6pX5K6Zp8Y")
candidates = searcher.search_raw(track)
scorer = ScoreMatchCalculator()
for cand in candidates:
expl = scorer.explain_score(cand, track, strict=True)
print(f"{expl['yt_title']} – total score {expl['total_score']:.2f}")
This snippet accesses the same search_raw and explain_score methods used by the CLI's explain mode, enabling integration into custom debugging workflows or automated quality assurance pipelines.
Summary
- The
--explainflag triggers a dry-run analysis inspotifysaver/cli/commands/download/track.pythat displays match scoring without executing downloads. ScoreMatchCalculator.explain_score()computes component scores for duration, artist, title, and album metadata, returning a detailed breakdown dictionary.- The
search_raw()method fetches all YouTube Music candidates rather than selecting a single best match, enabling comparative analysis across multiple videos. - Early return statements in the track processing logic prevent any file I/O or audio conversion from occurring.
- Both CLI users and Python developers can leverage this functionality to debug mismatches, understand ranking decisions, or refine scoring thresholds without consuming storage bandwidth.
Frequently Asked Questions
What scoring components does the explain mode display?
The explain mode displays four primary scoring components: duration similarity, artist overlap percentage, title string similarity, and an album match bonus. Each component contributes to a total score between 0 and 1, with the passed boolean indicating whether the candidate meets the strict matching threshold defined in the scorer configuration.
Does explain mode consume YouTube API quota?
Yes, explain mode executes live searches against YouTube Music via the search_raw method, which consumes API quota units. However, it avoids the additional quota and bandwidth costs associated with audio stream analysis or file downloads since it stops after the search and scoring phase.
Can I use explain mode with playlists and albums?
Yes, the --explain flag propagates through the processing hierarchy for albums and playlists. When processing these collections, the flag passes to each individual track's processing logic in sequence, displaying score breakdowns for every track in the collection without downloading any files.
How does explain mode prevent actual downloads?
The process_track function in spotifysaver/cli/commands/download/track.py contains explicit return statements immediately after printing the score explanations. This exits the function before reaching the downloader.download_track_cli invocation and file-writing logic, ensuring no audio files or metadata are persisted to storage.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →