A Chrome extension that recreates the classic Winamp 2.x player as a standalone window to control YouTube Music, Spotify, and Amazon Music. Pure nostalgia — no frameworks, no build tools, no image assets.
| Feature | Description |
|---|---|
| Play / Pause / Stop | Full transport control over YouTube Music, Spotify, and Amazon Music |
| Previous / Next | Navigate the track queue |
| Seek bar | Scrub through the current track |
| Volume slider | Adjust volume (0–100) |
| Track info marquee | Scrolling title + artist with seamless loop |
| LCD time display | Green segmented digits — click to toggle elapsed/remaining |
| Blinking pause | Time display blinks when paused, just like the original |
| Shuffle / Repeat | Toggle shuffle and cycle repeat modes (off → all → one) |
| Eject button | Opens or focuses the active music service tab |
| Connection indicator | Green dot when connected, red when no music tab found |
| Keyboard shortcuts | Full keyboard control (see table below) |
| WSZ skin support | Load classic Winamp skins — double-click the title bar |
| Equalizer | 10-band EQ with graph, ON/AUTO buttons, and skinnable sliders |
| Playlist editor | Scrollable track list with queue from the active service |
| Service | Bridge | API |
|---|---|---|
| YouTube Music | bridge-youtube.js |
#movie_player embedded player API |
| Spotify | bridge-spotify.js |
DOM selectors + mediaSession |
| Amazon Music | bridge-amazon.js |
Maestro player API + DOM fallbacks |
┌──────────────────────┐ ┌───────────────────┐ ┌────────────────────────┐
│ Winamp Window │ chrome │ Service Worker │ chrome │ Content Script │
│ winamp.html/css/js │ ──────→ │ background.js │ ──────→ │ content.js (isolated) │
│ │ runtime │ │ tabs │ │ │
│ Renders UI │ ←────── │ Routes messages │ ←────── │ ↓ postMessage │
│ Polls state @500ms │ │ Manages window │ │ Bridge (page context) │
│ │ │ Finds music tab │ │ Service-specific API │
└──────────────────────┘ └───────────────────┘ └────────────────────────┘
- Winamp ↔ Service Worker —
chrome.runtime.sendMessageconnects the popup window to the extension backend - Service Worker ↔ Content Script —
chrome.tabs.sendMessagetargets the music service tab specifically - Content Script ↔ Bridge —
window.postMessagecrosses the isolated-world / page-context boundary (required becauseCustomEvent.detailobjects are not cloneable between worlds)
The UI polls for playback state every 500ms. This is intentionally simple:
- Self-healing: no persistent connection to break
- Wakes idle service workers automatically
- Avoids race conditions from event-driven state sync
youtube_winamp/
├── manifest.json MV3 extension configuration
├── background.js Service worker — window lifecycle + message routing
├── content.js Content script relay (isolated world)
├── bridge-youtube.js YouTube Music bridge (MAIN world, #movie_player API)
├── bridge-spotify.js Spotify bridge (MAIN world, DOM + mediaSession)
├── bridge-amazon.js Amazon Music bridge (MAIN world, maestro API + DOM)
├── skin-loader.js WSZ skin parser — extracts BMP sprites into CSS
├── winamp.html Winamp window markup
├── winamp.css Pure CSS Winamp 2.x layout (275×116)
├── winamp.js UI controller — polling, rendering, event handlers
├── vendor/
│ └── jszip.min.js ZIP extraction for .wsz skin files
├── skins/
│ └── base.wsz Default Winamp skin
├── fonts/
│ ├── PressStart2P-latin.woff2
│ └── PressStart2P-latin-ext.woff2
└── icons/
├── icon16.png
├── icon48.png
└── icon128.png
No build step. No node_modules. No React. Just files.
- Clone or download this repository
- Open
chrome://extensionsin Chrome - Enable Developer mode (top right toggle)
- Click Load unpacked and select the
youtube_winamp/folder - The extension icon appears in your toolbar
- Open any supported music service (YouTube Music, Spotify, or Amazon Music) and start playing a song
- Click the YouTube Winamp extension icon in the toolbar
- A Winamp-style popup window opens and auto-connects to your music tab
- Control playback from the Winamp window — all actions are mirrored in the music service
Tip: If the connection dot is red, make sure you have a music service tab open and try reloading it.
All shortcuts work when the Winamp window is focused:
| Key | Action |
|---|---|
Space or P |
Play / Pause toggle |
S |
Stop |
← |
Seek backward 5 seconds |
→ |
Seek forward 5 seconds |
Ctrl/Cmd + ← |
Previous track |
Ctrl/Cmd + → |
Next track |
↑ |
Volume up (+5) |
↓ |
Volume down (-5) |
Double-click the title bar to load a custom .wsz Winamp skin. The skin loader:
- Extracts BMP sprite sheets from the ZIP archive
- Maps sprite coordinates using the Winamp 2.x skin spec
- Generates CSS with data URI backgrounds for each UI element
- Parses
VISCOLOR.TXTfor visualizer colors - Parses
PLEDIT.TXTfor playlist editor colors
Skins are processed entirely in memory and are not stored.
The entire Winamp skin layout is pure CSS — no bitmap assets for the base structure:
- 3D beveled borders using directional
border-color(highlight top-left, shadow bottom-right) - LCD green glow via
text-shadowwith transparent green - Segmented digit look using the bundled
Press Start 2Ppixel font - Transport icons as inline SVGs with CSS fill colors
- Titlebar grip pattern using
repeating-linear-gradient - Button press effect by swapping border highlight/shadow colors on
:active - Blinking animations using
@keyframeswithstep-endtiming for authentic LCD blink
| Decision | Rationale |
|---|---|
| Polling over events | Service workers can go idle; polling self-heals. Simpler than maintaining persistent connections. |
| postMessage over CustomEvent | CustomEvent detail isn't cloneable across isolated/page context boundary in Chrome extensions. |
| Bundled font | Extension CSP can block external font loading; bundling guarantees the pixel font always renders. |
| SVG transport icons | CSS triangle hacks are fragile; inline SVGs render crisply at any size and are easy to color. |
| No build tools | The extension is small enough that raw files are simpler to develop, debug, and distribute. |
| Seek slider normalized to 0–1000 | HTML range inputs work with integers; 1000 steps gives smooth seeking without floating point issues. |
| Per-service bridges | Each music service has a wildly different DOM and API; isolated bridges keep logic clean and maintainable. |
Window opens but shows red dot (no music tab found):
- Make sure you have YouTube Music, Spotify, or Amazon Music open in a tab
- Reload the music tab after installing/updating the extension (the content script injects on page load)
Buttons don't respond:
- Reload the music service tab — the bridge script needs to re-inject
- Check
chrome://extensionsfor any error messages on the extension card
Font looks wrong:
- The
Press Start 2Pfont is bundled locally — if it doesn't load, check the browser console in the Winamp window for font loading errors
MIT