Skip to content

AnujYadav-Dev/SonicBoard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

✦ SonicBoard

Download any Spotify playlist or track as MP3 320k - straight to your PC

Full metadata Β· Synced lyrics Β· Album art Β· Genre tags Β· Smart audio matching


Open in Colab Spotify API License: MIT



✦ What is SonicBoard?

SonicBoard is a Google Colab notebook that turns any Spotify playlist or individual track into a clean, fully-tagged MP3 collection - downloaded as a ZIP directly to your computer. No CLI setup. No local Python environment. No subscriptions. Just paste, run, and receive.

Feature Details
🎡 Audio Quality MP3 at 320 kbps via yt-dlp
🏷️ Metadata Title, Artist, Album Artist, Album, Year, Track β„–, Disc β„–, ISRC, Spotify URL, Cover Art, Genre
πŸ“ Lyrics Synced .lrc preferred; 4-source cascade: LRCLib β†’ lyrics.ovh β†’ Genius β†’ syncedlyrics
🎭 No Lyrics Fallback Animated placeholder .lrc embedded into MP3 - works in any folder
🎯 Smart Audio Matching Scores up to 8 candidates before downloading; rejects karaoke, instrumentals, covers, tributes automatically
πŸ”‡ Audio Track Guard bestaudio[acodec!=none] format filter prevents silent/background-only alternate streams
🧹 Clean Audio SponsorBlock removes intros, outros, self-promos; duration filter rejects extended mixes
🎼 Genre Tags Spotify artist data with automatic Last.fm fallback (Spotify genres empty since 2025)
πŸ”— URL Support Paste a playlist URL or a single track URL β€” both work
πŸ“ Output Playlist Name/MP3/ and Playlist Name/LRC/ inside a single ZIP
☁️ Platform Google Colab - runs entirely in the cloud, no local install


πŸš€ Quick Start

1 - Get Spotify API Credentials (free, 2 min)

  1. Go to developer.spotify.com/dashboard and log in
  2. Click Create App
  3. Set Redirect URI to https://open.spotify.com
  4. Under APIs used, check βœ… Web API β†’ Save
  5. Copy your Client ID and Client Secret

⚠️ February 2026 API Note: Spotify now requires an active Premium subscription on the account that owns the API app. Dev Mode apps will return a 403 for non-Premium accounts.

2 - Get a Last.fm API Key (optional but recommended)

Spotify has silently emptied most artist genre data since early 2025. SonicBoard uses Last.fm as a fallback to keep genre tags accurate.

  1. Go to last.fm/api/account/create
  2. Create a free API account
  3. Copy your API Key into Cell 2

If left blank, genre tags will only populate when Spotify returns data directly.

3 - Open the Notebook

Open in Colab

4 - Run

Cell Action
Cell 1 Installs all dependencies (spotipy, yt-dlp, mutagen, ffmpeg, syncedlyrics, etc.)
Cell 2 Paste your Spotify Client ID, Client Secret, and optional Last.fm API Key
Cell 3 Paste a Spotify playlist URL or a single track URL
Cell 4 Runs the full downloader β€” sit back

Runtime β†’ Run all and you're done. A ZIP file will download to your PC automatically when finished.



πŸ“‚ Output Structure

Playlist:

Playlist Name/
β”œβ”€β”€ MP3/
β”‚   β”œβ”€β”€ Blinding Lights - The Weeknd.mp3
β”‚   β”œβ”€β”€ Levitating - Dua Lipa.mp3
β”‚   └── ...
└── LRC/
    β”œβ”€β”€ Blinding Lights - The Weeknd.lrc
    β”œβ”€β”€ Levitating - Dua Lipa.lrc
    └── ...

Single track:

Song Title - Artist Name/
β”œβ”€β”€ MP3/
β”‚   └── Song Title - Artist Name.mp3
└── LRC/
    └── Song Title - Artist Name.lrc

Each .mp3 file is embedded with:

  • ID3v2.3 tags: Title, Artist, Album Artist, Album, Year, Track Number, Disc Number
  • ISRC (TSRC) and Spotify URL (WOAF)
  • Album Art (APIC) - fetched from Spotify's CDN
  • Inline Lyrics (USLT) - lyrics always embedded inside the MP3 itself, so they work in any folder regardless of where the .lrc file is
  • Genre (TCON) - from Spotify artist data, with Last.fm fallback
  • Comment (COMM) - download date and ISRC for reference


πŸ”§ How It Works

Spotify URL (playlist or track)
         β”‚
         β–Ό
Spotify API ──► Track metadata (title, artist, ISRC, cover, genre…)
         β”‚       β€’ playlist/ β†’ paginates all tracks via playlist_items()
         β”‚       β€’ track/    β†’ fetches single track via sp.track()
         β”‚       Both paths produce identical track dicts
         β–Ό
YouTube Smart Matching (yt-dlp)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Phase 1 β€” Candidate scoring                          β”‚
β”‚    β€’ Fetch up to 8 candidates via extract_flat        β”‚
β”‚    β€’ Score each: title words + artist name match      β”‚
β”‚    β€’ Hard -100 penalty: karaoke / instrumental /      β”‚
β”‚      cover / tribute / backing track / no vocals      β”‚
β”‚    β€’ Bonus: official / audio / vevo signals           β”‚
β”‚    β€’ Duration gate: Β±35–45 s window                   β”‚
β”‚    β€’ Download the highest-scoring candidate directly  β”‚
β”‚                                                       β”‚
β”‚  Phase 2 β€” Plain-query fallback (if Phase 1 fails)    β”‚
β”‚    β€’ Simple ytsearch1 on "Artist Title"               β”‚
β”‚    β€’ Wider duration window (Β±45–60 s)                 β”‚
β”‚                                                       β”‚
β”‚  Always: bestaudio[acodec!=none] format filter        β”‚
β”‚          prevents silent alternate audio streams      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
Lyrics Cascade
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  1. LRCLib      - synced .lrc (best quality) β”‚
β”‚  2. lyrics.ovh  - plain text, no key needed  β”‚
β”‚  3. Genius      - scraping, Hindi/non-Englishβ”‚
β”‚  4. syncedlyrics - Musixmatch, Apple, NetEaseβ”‚
β”‚  βœ—  None found  - funny animated placeholder β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
Genre Resolution
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  1. Spotify artist.genres                    β”‚
β”‚  2. Last.fm artist.getTopTags (fallback)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
mutagen ID3v2.3 embed (lyrics always go into USLT tag)
         β”‚
         β–Ό
ZIP  ──►  files.download()  ──►  Your PC


πŸ”— URL Support

Cell 3 accepts either URL type β€” no configuration needed, SonicBoard detects automatically:

Type Example URL ZIP name
Playlist https://open.spotify.com/playlist/5f080ra... Playlist Name.zip
Track https://open.spotify.com/track/4cOdK2wGLETKBW... Song Title - Artist.zip

Any other URL format (album, artist, podcast) will raise a clear error in Cell 3 before any API call is made.



🎯 Smart Audio Matching

The previous approach searched YouTube and blindly downloaded the first result that passed a duration check. This caused two recurring problems: karaoke/instrumental versions being downloaded instead of originals, and YouTube's multi-track audio system sometimes exposing a background-music-only stream as the "best" audio format.

SonicBoard now uses a two-phase matching system:

Phase 1 β€” Scored candidate selection

Instead of downloading the first result, the script fetches up to 8 candidates using extract_flat (fast - no audio downloaded yet) and scores every result before committing to any download.

Signal Score
Title words matching the track +3 per word
Artist name words matching +2 per word
"official", "audio", "vevo", "music video" in title +2 each
karaoke, instrumental, cover, tribute, backing track, no vocals, minus one, remake, rendition βˆ’100 (hard penalty)

Only the highest-scoring candidate that also passes the duration gate (Β±35 s) gets downloaded - directly by URL, not via another search. If the winning score is deeply negative (all candidates are non-originals), the phase fails cleanly rather than downloading something wrong.

Phase 2 β€” Plain fallback

If Phase 1 finds nothing, a simple Artist Title query is used as a last resort with a slightly wider duration window.

Audio track guard

The format selector was changed from bestaudio/best to bestaudio[acodec!=none]/bestaudio/best. This prevents yt-dlp from picking a YouTube multi-track alternate stream (often a background-music-only dub track) that can surface as the top-ranked audio format.



πŸ“ Lyrics System

SonicBoard tries four sources in order, stopping at the first hit:

Priority Source Type Notes
1 LRCLib Synced + Plain /api/get by duration; /api/search fallback with best-match picking
2 lyrics.ovh Plain Free REST API, no key, no scraping
3 Genius Plain Scraping fallback; strong Hindi/non-English coverage
4 syncedlyrics Synced + Plain Tries Musixmatch, Apple Music, NetEase; bypasses anti-scrape

When no source finds lyrics, a fun animated placeholder .lrc is written instead of leaving the file empty. The placeholder is also embedded directly into the MP3's USLT tag - so it shows up correctly in your music player regardless of whether the .lrc file is in the same folder as the MP3 or not.



🎼 Genre System

Spotify has largely stopped returning genre data for artists since early 2025. SonicBoard handles this with a two-layer approach:

  1. Fetch genres from sp.artist() - used if Spotify returns any
  2. Fall back to Last.fm artist.getTopTags - filters out noise tags (e.g. seen live, favorites, beautiful) and only keeps tags with a community count β‰₯ 10

Results are cached per artist to avoid redundant API calls across the same playlist.



πŸ› οΈ Tech Stack

Library Role
spotipy Spotify Web API client - playlist & track data
yt-dlp YouTube audio extraction & candidate scoring
ffmpeg Audio transcoding to MP3 320k
mutagen ID3v2.3 metadata embedding
requests HTTP - cover art, lyrics APIs
beautifulsoup4 HTML parsing for Genius lyrics scraping
syncedlyrics Lyrics package - Musixmatch, Apple Music, NetEase
LRCLib Primary lyrics source (synced + plain)
lyrics.ovh Secondary lyrics source (plain, no key)
Last.fm API Genre fallback (artist.getTopTags)


⚠️ Spotify API Compatibility

This notebook is updated for the February 2026 Spotify Web API changes:

Change Old Fixed
Playlist items endpoint sp.playlist_tracks() β†’ /tracks sp.playlist_items() β†’ /items βœ…
Track key in response item['track'] only item.get('track') or item.get('item') βœ…
Single track support Playlists only sp.track() added for track/ URLs βœ…
Dev Mode requirement Any account Premium required on app-owner account
Artist genre data Usually populated Mostly empty - Last.fm fallback added βœ…


πŸ™‹ FAQ

Q: Is this legal? SonicBoard downloads audio from YouTube, not from Spotify directly. Usage is subject to YouTube's Terms of Service. This tool is intended for personal, offline use of content you have rights to access.

Q: Will it work on free Spotify accounts? The Spotify API credentials (Client ID/Secret) need to belong to a Premium account owner as of February 2026. The playlist itself can be public.

Q: What if a track fails to download? The script will skip it, log it as failed, and continue. A summary is printed at the end. You can re-run the notebook - already downloaded files are skipped automatically.

Q: Can I paste a single song link instead of a playlist? Yes. Paste any open.spotify.com/track/... URL into Cell 3 and SonicBoard will download just that one song with full metadata, lyrics, and album art β€” same quality and output structure as a playlist, just one item.

Q: Can I use this for albums? Not yet. Album URL support is a planned enhancement β€” PRs welcome.

Q: Why did I get an instrumental or karaoke version before? The old script downloaded the first YouTube result that matched the duration, with no check of what the video actually was. The new smart matching system scores up to 8 candidates and applies a hard penalty to any result whose title contains karaoke, instrumental, cover, tribute, or similar keywords. See the Smart Audio Matching section for full details.

Q: What if lyrics aren't found? All four sources are tried in order (LRCLib β†’ lyrics.ovh β†’ Genius β†’ syncedlyrics). If all fail, a fun animated placeholder .lrc is created and embedded into the MP3 so it always displays correctly in your music player.

Q: Why do lyrics work from any folder? Lyrics are embedded directly inside the MP3 file via the USLT ID3 tag. Your player reads them from the file itself - it doesn't need to find a matching .lrc file in the same folder. The separate .lrc file in the LRC/ folder is a bonus for players that support external synced lyrics.

Q: Do I need a Last.fm API key? It's optional but recommended. Without it, genre tags will only appear when Spotify returns data directly, which has been rare since early 2025.



πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.



Made with 🎧 and too much chai

If SonicBoard saved you time, consider starring the repo ⭐

Releases

No releases published

Packages

 
 
 

Contributors