Skip to content

narekp/playlist_to_cd

Repository files navigation

playlist_to_cd

playlist_to_cd is a small macOS desktop utility that turns Spotify playlist CSV exports into CD-ready output: either an MP3 CD (~700 MB, bitrate-fitted) or an Audio CD (44.1 kHz / 16-bit stereo WAV).

What problem it solves

Burning a Spotify playlist to a physical CD requires downloading each track, normalising formats, fitting the collection to disc capacity, applying metadata, and renumbering files. This project automates that pipeline.

How it works (and why it's free)

You export your Spotify playlist to CSV with Exportify (free, no account needed). The app then:

  • Finds each track on YouTube via yt-dlp, using smart search variants (artist + title, with fallbacks for parenthesised titles, multi-artist tracks, etc.) and tries up to 3 candidates per variant.
  • Validates before downloading: checks YouTube metadata first. If the duration differs from Spotify’s by more than ±10%, it skips that candidate and tries the next—no wasted downloads.
  • Validates after downloading: runs ffprobe on each file. If the actual duration still doesn’t match, the file is rejected and deleted. Rejected and failed tracks are written to CSVs so you can review.
  • Fits to disc: for MP3 CD mode, starts at 320 kbps and automatically steps down (256→192→160→128) until the collection fits in ~700 MB.
  • Resumes: tracks progress in state.json; re-run after a stop and it skips already-accepted tracks.

No Spotify API, no paid services, no account friction—just CSV in, CD-ready output out.

What it currently does

There are two entry points:

Entry point Interface Scope
main_original.py Tkinter GUI desktop app Full workflow: CSV parsing, YouTube download via yt-dlp, duration validation, post-processing (MP3 CD or Audio CD)
main.py CLI Post-processing only: takes an existing directory of MP3 files and runs the MP3 CD or Audio CD pipeline

The core logic (artist parsing, filename safety, search query building, ffmpeg operations) lives in reusable modules under core/ and modes/.

Recommended path

The supported product path is:

  1. Export the Spotify playlist to CSV with Exportify.
  2. Open the Tkinter desktop app.
  3. Choose the CSV, choose an output folder, select MP3 CD or Audio CD, and run.

That CSV-first flow is the one this project is actively optimized around.

Current limitations

  • main.py cannot drive the full CSV-to-CD workflow; download/acquisition is only available through the desktop app (main_original.py).
  • core/query.py (search query building) is extracted but only called from the monolith; it is not yet wired into main.py.
  • No web app, server mode, or headless full-workflow entry point exists.
  • Requires ffmpeg, ffprobe, and yt-dlp installed and available on PATH.

Current workflow

Full workflow (desktop app)

  1. Export a Spotify playlist to CSV via Exportify.
  2. Run python main_original.py.
  3. Select the CSV, choose an output folder and output mode (MP3 CD or Audio CD).
  4. The app downloads tracks from YouTube, validates durations, and runs the selected post-processing pipeline.
  5. Output is a directory of numbered, metadata-tagged files ready to burn.

Post-processing only (CLI)

If you already have a directory of MP3 files (e.g. from a previous interrupted run):

# MP3 CD mode (requires accepted duration)
python main.py --mode mp3 --processed-dir /path/to/mp3s --accepted-duration-sec 3600

# Audio CD mode
python main.py --mode audio --processed-dir /path/to/mp3s

Example workflow

Full workflow (GUI):

  1. Export your Spotify playlist as a CSV using Exportify and save as CSV.
  2. Run python main_original.py, choose the CSV and an output folder, pick "MP3 CD" or "Audio CD", then Start.
  3. When finished, burn the output folder to disc (for Audio CD, burn the audio_cd_ready/ subfolder).

Post-processing only (CLI):

# Folder of MP3s → MP3 CD (~700 MB). Example: 1 hour of accepted audio.
python main.py --mode mp3 --processed-dir ./my_tracks --accepted-duration-sec 3600

# Same folder → Audio CD WAVs
python main.py --mode audio --processed-dir ./my_tracks

Why the project is CSV-first

An experimental branch, feat/spotify-source, explored a direct Spotify-connected route by adding spotipy plus local environment and callback configuration.

That route is not the chosen product direction for this app:

  • It adds Spotify app registration, local callback setup, and per-user credential/config management.
  • It creates more account/auth friction for a simple local utility.
  • It is a worse fit for a packaged desktop app than a plain CSV import flow.
  • It still does not remove the downstream dependency on yt-dlp/YouTube matching for acquisition.

The decision is to keep the app centered on a simple user-owned workflow: export the playlist to CSV, then feed that CSV back into the desktop app. That path is more practical, easier to support, and avoids tying normal use to Spotify-specific auth requirements.

How to run

Prerequisites

  • Python 3.9+
  • ffmpeg and ffprobe on PATH
  • yt-dlp on PATH (for the full workflow via main_original.py)

Install

pip install -r requirements.txt

(requirements.txt contains pytest and ruff for testing and linting.)

Linting

ruff check .
ruff check . --fix   # auto-fix safe issues

How to run tests

pytest

Test configuration lives in pyproject.toml. The suite currently includes 83 tests, including coverage for the extracted modules plus a minimal GUI smoke test. Tests mock external boundaries (ffmpeg, ffprobe, subprocess, filesystem) and do not require network access.

Building the macOS app

To package the GUI as a standalone macOS .app and local .dmg:

  1. Prerequisites: PyInstaller (pip install pyinstaller) and the external binaries in packaging/bin/. See packaging/bin/README.md for how to obtain ffmpeg, ffprobe, and yt-dlp.

  2. Build:

    ./packaging/build_macos.sh
  3. Output:

    • dist/playlist_to_cd.app
    • dist/playlist_to_cd_0.1.0.dmg

The build script uses the project .venv if it exists and has PyInstaller installed.

Installing and running from DMG (local)

  1. Open dist/playlist_to_cd_0.1.0.dmg.
  2. Copy playlist_to_cd.app to Applications (or another local folder).
  3. Launch the app from Finder.

Because this build is unsigned and not notarized, macOS Gatekeeper may block first launch. If that happens, right-click the app and choose Open. If needed, remove quarantine:

xattr -dr com.apple.quarantine "/Applications/playlist_to_cd.app"

Target machine dependency expectations

  • Preferred: Build with ffmpeg, ffprobe, and yt-dlp present in packaging/bin/ so they are bundled inside the app.
  • Fallback: If they are not bundled, the target Mac must provide those binaries on PATH, or the app will show missing-dependency errors at startup.

About

Turn any Spotify playlist into a ready-to-burn CD

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors