The Problem

Moving a music library from Spotify to YouTube Music often requires manually re‑creating playlists, searching each track on the new platform, and reconciling missing tracks. The process is time‑consuming and error‑prone, especially when headers expire or network quotas are hit.

What This Does

Spotify2YoutubeMusic automates the transfer with a graphical interface and a one‑step setup (S2YM.bat / S2YM.sh). The core logic lives in copy_playlists.py (36 functions, 1 class) which handles Spotify client creation, YouTube‑Music client initialization, playlist copying, and progress persistence. The user interface is defined in ui.py (57 functions, 2 classes) providing widgets, config loading/saving, batch‑size controls, and real‑time progress updates. The app reads and writes song_cache.json, migration_report_*.json, and the user’s config file (see requirements.txt for dependencies). A small set of helper functions (load_config, save_config, initialize_clients) are shared between the two modules.

How It Is Wired

Execution starts when the batch script runs python ui.py, which creates the Tkinter main window and calls initialize_clients to obtain Spotfiye and YouTube‑Music API clients. From there, the internal call graph funnels through a few hub functions:

Hub functionTimes called (internal)Dependent callers
append_response33 (from _copy_playlists)_copy_playlists, _copy_liked_songs, error_callback
get_ytmusic_client12initialize_clients, _copy_playlists, _copy_liked_songs
get_spotify_client5get_spotify_liked_songs, get_spotify_playlist_tracks
check_configuration5initialize_clients, reset_progress_bar

The deepest nesting (max indent 15) appears in both copy_playlists.py and ui.py, and broad except clauses swallow errors in those same files. Two 6‑line code blocks are duplicated across the pair, violating DRY.

How To Use It

# 1️⃣ Clone the repo (verbatum)
git clone https://github.com/moses-y/Spotify2YoutubeMusic

# 2️⃣ Run the one‑step setup (Windows) or (macOS/Linux)
#    This creates a venv, installs from requirements.txt, and launches the app.
S2YM.bat          # Windows
S2YM.sh           # macOS / Linux

# 3️⃣ First run will ask for Spotify credentials and a YouTube‑Music OAuth token; the app stores them in the config file.
# 4️⃣ Select playlists, adjust the batch‑size slider (1–20), and click “Copy Playlists”.
# 5️⃣ Progress, success rates, and a migration report are displayed and saved automatically.

No environment variables need to be set manually; the GUI prompts for the necessary keys and persists them in the config file created by load_config/save_config.

Real‑World Use

A user with a “Chill Vibes” Spotify playlist of 47 tracks can launch the app, pick the playlist, and let the tool search YouTube‑Music, cache results in song_cache.json, and add the tracks in batches of 10. If the YouTube‑Music headers expire mid‑run, the app pauses, refreshes headers, and resumes from the last saved batch, ultimately generating migration_report_Chill Vibes.json listing every track’s status.

Code Health & Issues

  • No test files – untested code paths repository‑wide.
  • No CI/CD pipeline – no automated build/test gate.
  • Dependencies declared without a lockfilerequirements.txt only; builds are not reproducible across environments.
  • Deep nesting (max indent 15) in copy_playlists.py and ui.py – control flow is hard to follow.
  • Broad exception handling in the same two files – errors may be silently swallowed.
  • Oversized files – 1256 combined lines across ui.py and copy_playlists.py exceed typical cognitive load.
  • Duplicated 6‑line blocks across copy_playlists.py and ui.py – violates DRY.
  • Missing Dependabot/Renovate – no automated dependency updates (code‑health audit item).

The Bottom Line

The tool delivers a functional, GUI‑driven migration path from Spotify to YouTube Music with useful features like smart caching and progress‑saving resume. However, the codebase suffers from high cognitive load, unhandled exception paths, and missing reproducibility guards (no lockfile, no CI, no tests). It is suitable for personal, one‑off transfers where the user can tolerate occasional manual fixes, but teams requiring maintainability should plan to split the monolithic files, add specific exception handling, and introduce a dependency lockfile and CI gate.