Skip to content

Repository files navigation

🎵 ytm-winamp

YouTube Music in classic Winamp — era-correct, country-localized, zero accounts.

GitHub release Build License Platform Downloads

Quick start · Features · Era radio · How it works · FAQ

Winamp playing Crystal Waters via ytm-winamp

Actual capture: Crystal Waters streaming at 192 kbps with live ICY titles. Really whips the llama's ass.


✨ Features

📻 Never-ending era radio One command starts a shuffled 1995–2005 hit parade that refills itself — the bridge watches the playlist and mixes in fresh tracks before you run out, never repeating a song
🌍 Localized to your country Your IP's country is auto-detected and ~40% of the queue is that country's actual number-one hits of the era — fetched from real chart archives, never guessed
Snappy controls Upcoming tracks are prefetched and cached to disk; pressing next starts the next song in a fraction of a second
🏷️ Real titles in Winamp ICY (SHOUTcast-style) metadata, so the title bar and playlist show Artist – Title like a proper radio
Seeking The position slider works on cached tracks (HTTP Range requests)
🎧 Public playlist radio mix queues any public YouTube Music playlist by name — no auth needed
🖥️ System tray controller Now-playing menu, playback controls, era radio one click away
🎯 Plays anything Search queries, video URLs, whole YouTube/YouTube Music playlists
❤️ Liked songs Optional: your YouTube Music likes via ytmusicapi auth
📦 Single-file exe No Python, no PATH surgery — download and go
🪶 No accounts, no API keys For everything above except liked songs

🚀 Quick start

  1. Download ytm-winamp-setup.exe and run it — a proper installer wizard: the app, Winamp (via winget), portable yt-dlp/ffmpeg, shortcuts, and the default Winamp Modern theme.
  2. Check "Start the era radio" on the finish page.
  3. That's it — use the desktop/Start-menu shortcut next time, or ytm-winamp from any terminal.

Prefer portable? Grab the bare ytm-winamp.exe instead and run ytm-winamp setup once yourself.

Install from source instead
pipx install .          # or: pip install .[liked]
ytm-winamp setup
ytm-winamp

Requires Python 3.10+. Everything setup does is idempotent — whatever is already installed is detected and left alone.

📻 The era radio, localized

Bare ytm-winamp (or ytm-winamp era) starts a never-ending radio of Winamp-era hits, roughly 1995–2005. The bridge watches Winamp's playlist position and appends a fresh batch of tracks before the queue runs out — with no repeats. About 60% is the worldwide canon that was on every playlist everywhere; the other 40% comes from your own country's charts of those years. Want a fixed queue instead? ytm-winamp era --no-radio.

Local chart data sources:

Source Countries Notes
Wikipedia national number-one lists (CC-BY-SA) 🇩🇪 🇦🇹 🇨🇭 🇮🇹 🇪🇸 🇳🇱 🇫🇷 🇮🇪 🇩🇰 🇫🇮 🇨🇦 🇯🇵 Per-year lists, List of number-one hits of YYYY (…) style
Wikipedia decade/all-time lists 🇬🇧 🇳🇿 🇸🇪 🇳🇴 Year-filtered while parsing
Wikipedia year-end charts 🇺🇸 🇦🇺 🇧🇪 Billboard Hot 100 year-ends; ARIA year-end top 100; Ultratop Wallonia
slagerlistak.hu 🇭🇺 Year-end Rádiós Top 40 charts

That's 20 countries and counting. No list for yours? You get the global parade with a console note — and adding a country is usually a one-line page pattern in charts.py (COUNTRY_SOURCES). PRs welcome.

ytm-winamp era --country DE     # force a country (code or name)
ytm-winamp era --global-only    # skip local charts
ytm-winamp era -n 50            # bigger queue (default 25)

🔧 How it works

Winamp 5.x can't fetch YouTube directly — the googlevideo CDN rejects its HTTP client ([access denied], if you ever tried). So a tiny localhost bridge does the fetching instead:

            search / URL / charts                 pre-resolved, cached
YouTube ───────────────▶ yt-dlp ──▶ ffmpeg ──▶ MP3 ──▶ http://127.0.0.1:8797 ──▶ Winamp
                                        (disk cache + prefetch)      (ICY titles)
  • Stream URLs resolve when a track downloads, never when enqueued — googlevideo expiry is a non-issue
  • Two download workers, one retry per track, graceful 502s — flaky networks don't freeze the player
  • Titles ride along as ICY metadata; the playlist keeps #EXTINF titles like it's 1999

🎛 Commands

Command What it does
ytm-winamp The era radio (same as era)
ytm-winamp era [--country X] [--global-only] [--no-radio] [-n N] Never-ending era radio, optionally localized
ytm-winamp play <query or URL> [-n N] Search, video, or whole playlist
ytm-winamp mix <name> [--list] [-n N] Queue a public YouTube Music playlist found by name
ytm-winamp tray System-tray controller (now playing, playback controls)
ytm-winamp liked [--shuffle] Your YouTube Music liked songs (auth needed)
ytm-winamp search <query> [-n N] List results with URLs
ytm-winamp setup First-run onboarding: Winamp + tools + theme
ytm-winamp serve Run the bridge in the foreground (debugging)
⚙️ Configuration reference
Setting How
Winamp path set YTM_WINAMP_EXE if Winamp isn't in the default location
Bridge port --port (default 8797)
Bridge log %TEMP%\ytm-winamp-bridge.log
Track cache %TEMP%\ytm-winamp-cache (up to 32 tracks, LRU)
Portable tools %USERPROFILE%\.ytm-winamp\bin
YT Music auth %USERPROFILE%\.ytm-winamp\ytmusic.json
Era/geo data %USERPROFILE%\.ytm-winamp\ (country.json, charts_*.json, era_cache.json)
❤️ Liked songs: one-time auth

Reading your liked songs requires a YouTube Music login via ytmusicapi (bundled in the exe). Run one of these once, then move the resulting file to %USERPROFILE%\.ytm-winamp\ytmusic.json:

ytmusicapi oauth     # recommended; needs a Google Cloud OAuth client
ytmusicapi browser   # paste request headers copied from music.youtube.com

Pass a different location with ytm-winamp liked --auth <path>.

🗺 Roadmap

  • Winamp-era radio with country-localized charts
  • ICY stream titles
  • Single-file exe + one-command setup
  • YouTube Music liked songs
  • Public YouTube Music playlists by name (mix, no auth)
  • System tray controller
  • Seeking (HTTP Range in the bridge)
  • More countries in COUNTRY_SOURCES (PRs welcome)
  • winget package submission (draft manifests in packaging/winget/)

❓ FAQ

Does this download videos?

No. Audio is streamed and transcoded on the fly; a small rolling cache of recent tracks (max 32) lives in %TEMP% and is evicted automatically.

Why does the first track take a few seconds?

Cold start: the bridge resolves and starts transcoding track one while prefetching the rest of the queue behind it. After that, cached tracks switch in a fraction of a second.

Winamp shows a video id instead of a title

You're on an old bridge from before ICY titles (v0.4.0). Re-run any play command — the bridge restarts itself on the new code.

🤝 Contributing

Issues and PRs are welcome — especially new country sources for COUNTRY_SOURCES (see the era section). Run the tests with python -m pytest tests/.

⚖️ Disclaimer

Unofficial hobby project, not affiliated with Winamp, YouTube, or Google. Streams audio through yt-dlp for personal playback; make sure your usage complies with YouTube's Terms of Service and applicable law. Chart data: Wikipedia (CC-BY-SA) and slagerlistak.hu.


Made with 🦙 for the llama-whipping community · MIT · back to top

About

Play YouTube Music tracks and playlists in classic Winamp via a local streaming bridge (yt-dlp + ffmpeg)

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages