{"id":49575175,"url":"https://github.com/rollecode/omnishuffle","last_synced_at":"2026-05-03T16:10:57.040Z","repository":{"id":330608369,"uuid":"1123348563","full_name":"rollecode/omnishuffle","owner":"rollecode","description":"📻 Unified music shuffler for Spotify, Pandora \u0026 YouTube.","archived":false,"fork":false,"pushed_at":"2026-03-26T14:03:25.000Z","size":112,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-02T13:33:31.322Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rollecode.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-26T17:25:21.000Z","updated_at":"2026-03-26T14:04:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rollecode/omnishuffle","commit_stats":null,"previous_names":["ronilaukkarinen/omnishuffle","rollecode/omnishuffle"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/rollecode/omnishuffle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rollecode%2Fomnishuffle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rollecode%2Fomnishuffle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rollecode%2Fomnishuffle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rollecode%2Fomnishuffle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rollecode","download_url":"https://codeload.github.com/rollecode/omnishuffle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rollecode%2Fomnishuffle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32575392,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-03T16:10:56.462Z","updated_at":"2026-05-03T16:10:57.033Z","avatar_url":"https://github.com/rollecode.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📻 OmniShuffle\n\n![Python](https://img.shields.io/badge/Python-4584b6?style=for-the-badge\u0026logo=python\u0026logoColor=white)\n![macOS](https://img.shields.io/badge/macOS-000000?style=for-the-badge\u0026logo=apple\u0026logoColor=white)\n![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge\u0026logo=linux\u0026logoColor=black)\n![Spotify](https://img.shields.io/badge/Spotify-1db954?style=for-the-badge\u0026logo=spotify\u0026logoColor=white)\n![Pandora](https://img.shields.io/badge/Pandora-5D47DB?style=for-the-badge\u0026logo=pandora\u0026logoColor=white)\n![YouTube Music](https://img.shields.io/badge/YouTube%20Music-ff0000?style=for-the-badge\u0026logo=youtube\u0026logoColor=white)\n![Last.fm](https://img.shields.io/badge/Last.fm-d51007?style=for-the-badge\u0026logo=lastdotfm\u0026logoColor=white)\n\nA unified command-line music shuffler that combines **Spotify, Pandora, and YouTube Music into a single streaming experience** with pianobar-style controls and Last.fm scrobbling support.\n\n\u003cimg width=\"664\" height=\"321\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b004218f-14ea-48e7-96f3-cd4fac0491a4\" /\u003e\n\n## Features\n\n- Shuffle music across multiple streaming services simultaneously\n- **Spotify Connect support** - 320kbps Premium streaming via spotifyd/librespot\n- Pianobar-style single-key controls for seamless interaction\n- Built-in Last.fm scrobbling with real-time now playing updates\n- Last.fm-based music discovery using similar artists/tracks\n- Pandora QuickMix support with automatic Tor proxy for geographic restrictions\n- Modern progress bar with brand colors and audio quality display\n- Genre tags from Last.fm shown in real-time\n- Heart icon (♥) for tracks loved on Last.fm\n- Love tracks synced to both Last.fm AND source service\n- Endless playback - queue auto-refills when empty\n\n## Requirements\n\n- Python 3.11+\n- mpv (with libmpv)\n- ffmpeg\n- pipx (recommended for installation)\n- Tor (optional, for Pandora outside USA - auto-starts when needed)\n- spotifyd or librespot (optional, for Spotify 320kbps streaming)\n\n## Installation\n\n### Quick install (recommended)\n\nRun the interactive installer that handles dependencies and configuration:\n\n```bash\ngit clone https://github.com/ronilaukkarinen/omnishuffle.git\ncd omnishuffle\n./install.sh\n```\n\nThe installer automatically detects your OS (macOS, Arch, Debian/Ubuntu, Fedora) and installs all required dependencies.\n\n### Manual installation\n\n#### macOS\n\n```bash\nbrew install mpv ffmpeg tor pipx\ngit clone https://github.com/ronilaukkarinen/omnishuffle.git\ncd omnishuffle\npipx install -e .\n```\n\n#### Arch Linux\n\n```bash\nsudo pacman -S mpv ffmpeg tor python-pipx\ngit clone https://github.com/ronilaukkarinen/omnishuffle.git\ncd omnishuffle\npipx install -e .\n```\n\n#### Debian/Ubuntu\n\n```bash\nsudo apt install mpv ffmpeg tor pipx\ngit clone https://github.com/ronilaukkarinen/omnishuffle.git\ncd omnishuffle\npipx install -e .\n```\n\n## Usage\n\nSimply run:\n\n```bash\nomnishuffle\n```\n\nThe player will start shuffling music from all configured sources.\n\n### Status display\n\n```\n▄▆ [SPOTIFY] Artist - Song Title ♥  (rock, metal)\n━━━━━━━━╸──────────────── 2:42/5:28  320kbps vorbis ⚡  vol 100%\n```\n\n- Brand-colored progress bar (green=Spotify, blue=Pandora, red=YouTube)\n- ⚡ indicates Spotify Connect (320kbps)\n- ♥ indicates track is loved on Last.fm\n- Genre tags from Last.fm\n\n## Controls\n\n| Key | Action |\n|-----|--------|\n| `n` | Next track |\n| `p` | Pause/Resume |\n| `Space` | Pause/Resume |\n| `+` | Love current track (syncs to Last.fm + source) |\n| `-` | Ban current track |\n| `(` | Volume down |\n| `)` | Volume up |\n| `l` | Refresh Last.fm recommendations |\n| `i` | Show track info (genres, quality, queue size) |\n| `S` | Shuffle queue |\n| `h` | Show help |\n| `q` | Quit |\n\n## Configuration\n\nConfiguration is stored in `~/.config/omnishuffle/config.json`.\n\n### Complete example config\n\n```json\n{\n  \"general\": {\n    \"default_mode\": \"shuffle\",\n    \"sources\": [\"spotify\", \"pandora\", \"youtube\"],\n    \"volume\": 100\n  },\n  \"spotify\": {\n    \"client_id\": \"your_client_id\",\n    \"client_secret\": \"your_client_secret\",\n    \"redirect_uri\": \"http://127.0.0.1:8080\"\n  },\n  \"pandora\": {\n    \"email\": \"your@email.com\",\n    \"password\": \"your_password\",\n    \"proxy\": \"socks5://127.0.0.1:9050\"\n  },\n  \"lastfm\": {\n    \"api_key\": \"your_api_key\",\n    \"api_secret\": \"your_shared_secret\",\n    \"username\": \"your_lastfm_username\",\n    \"password\": \"your_lastfm_password\"\n  }\n}\n```\n\n## Spotify setup\n\n### Basic setup (plays via YouTube)\n\n1. Go to [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)\n2. Click **Create app**\n3. Fill in the details:\n   - App name: `OmniShuffle`\n   - Redirect URI: `http://127.0.0.1:8080` (click Add)\n   - Which API/SDKs: Select **Web API**\n4. Click **Save**, then **Settings**\n5. Copy the **Client ID** and **Client Secret**\n\nOn first run, a browser opens for authorization.\n\n### Spotify Connect setup (320kbps Premium streaming)\n\nFor true 320kbps Spotify quality, install spotifyd:\n\n```bash\n# macOS\nbrew install spotifyd\nbrew services start spotifyd\n\n# Arch Linux\nyay -S spotifyd\nsystemctl --user enable --now spotifyd\n\n# Or install librespot directly\nyay -S librespot\n```\n\nConfigure spotifyd (`~/.config/spotifyd/spotifyd.conf`):\n\n```ini\n[global]\nusername = \"your_spotify_username\"\npassword = \"your_spotify_password\"\ndevice_name = \"OmniShuffle\"\ndevice_type = \"computer\"\nbitrate = 320\nbackend = \"pulseaudio\"  # Linux\n# backend = \"rodio\"     # macOS\n```\n\nOmniShuffle will automatically detect the spotifyd device and use it for Spotify tracks at 320kbps. You'll see:\n\n```\n✓ Spotify connected (320kbps via OmniShuffle)\n```\n\nIf no Spotify Connect device is found, it falls back to YouTube:\n\n```\n✓ Spotify connected (via YouTube fallback)\n```\n\n## Pandora setup\n\nPandora is only available in the USA. For users outside the USA, OmniShuffle auto-starts Tor with US exit nodes.\n\n### Creating a Pandora account (outside USA)\n\n1. Install Tor:\n   - macOS: `brew install tor`\n   - Arch: `sudo pacman -S tor`\n   - Debian/Ubuntu: `sudo apt install tor`\n2. Use Tor Browser or configure your browser to use SOCKS5 proxy `127.0.0.1:9050`\n3. Go to [pandora.com](https://www.pandora.com) and create a free account\n4. Create some stations based on artists/songs you like\n\n### Configuration\n\n```json\n{\n  \"pandora\": {\n    \"email\": \"your@email.com\",\n    \"password\": \"your_password\",\n    \"proxy\": \"socks5://127.0.0.1:9050\"\n  }\n}\n```\n\nOmniShuffle will:\n- Auto-start Tor with US exit nodes\n- Verify the exit node is in the US\n- Retry with a new circuit if needed\n- Use QuickMix (Shuffle) station that mixes from all your selected stations\n\nIf you're in the USA, leave proxy empty or omit it.\n\n## YouTube Music setup (optional)\n\nYouTube Music works without authentication - OmniShuffle searches YouTube and plays via yt-dlp.\n\nAuthentication is only needed for personal playlists. See the detailed setup in the wiki if needed.\n\n## Last.fm integration\n\nOmniShuffle has built-in Last.fm support - no external scrobblers needed.\n\nFeatures:\n- Real-time \"now playing\" updates\n- Automatic scrobbling (after 50% or 4 minutes)\n- Love track sync (pressing `+` loves on Last.fm + source service)\n- Smart recommendations based on your listening history\n\n### Getting Last.fm API credentials\n\n1. Go to [Last.fm API account creation](https://www.last.fm/api/account/create)\n2. Fill in the form (Application name: `OmniShuffle`)\n3. Copy the **API Key** and **Shared Secret**\n\n### Configuration\n\n```json\n{\n  \"lastfm\": {\n    \"api_key\": \"your_api_key\",\n    \"api_secret\": \"your_shared_secret\",\n    \"username\": \"your_lastfm_username\",\n    \"password\": \"your_lastfm_password\"\n  }\n}\n```\n\n### How recommendations work\n\nWhen Last.fm is configured, OmniShuffle uses it as the primary discovery engine:\n\n1. Fetches your loved tracks and top artists from Last.fm\n2. Finds similar tracks and artists using Last.fm's database\n3. Searches for these on YouTube Music\n4. Mixes with Pandora's personalized radio\n5. Shuffles everything together\n\nPress `l` to refresh recommendations anytime.\n\n## Audio quality\n\n| Source | Quality | Notes |\n|--------|---------|-------|\n| Spotify Connect | 320kbps Vorbis | Requires spotifyd/librespot + Premium |\n| Spotify (YouTube fallback) | ~128-160kbps | When no Connect device available |\n| Pandora Free | 64kbps AAC | |\n| Pandora Plus | 192kbps | |\n| Pandora Premium | 320kbps | |\n| YouTube | ~128-160kbps Opus | Best available audio |\n\n## Architecture\n\n```\n┌───────────────────────────────────────────────────────┐\n│                      OmniShuffle                      │\n├──────────┬──────────┬──────────┬──────────┬───────────┤\n│ Spotify  │ Pandora  │ YouTube  │ Last.fm  │ spotifyd  │\n│ (spotipy)│ (pydora) │ (ytmusic)│ (pylast) │ (320kbps) │\n└────┬─────┴────┬─────┴────┬─────┴────┬─────┴───────┬───┘\n     │          │          │          │             │\n     │          │          │    recommendations     │\n     │          │          │          │         playback\n     └──────────┴──────────┴──────────┘             │\n                     │                              │\n              ┌──────▼──────┐                       │\n              │   Shuffle   │◄──────────────────────┘\n              │    Queue    │\n              └──────┬──────┘\n                     │\n         ┌───────────┴───────────┐\n         ▼                       ▼\n   ┌──────────┐           ┌──────────┐\n   │   mpv    │           │ Spotify  │\n   │(Pandora/ │           │ Connect  │\n   │ YouTube) │           │ (320kbps)│\n   └────┬─────┘           └──────────┘\n        │\n        ▼\n   ┌──────────┐\n   │  pylast  │────► Last.fm (scrobble)\n   └──────────┘\n```\n\n## Dependencies\n\n| Package | Purpose |\n|---------|---------|\n| python-mpv | MPV playback control |\n| spotipy | Spotify API client |\n| pydora | Pandora API client |\n| ytmusicapi | YouTube Music API client |\n| yt-dlp | YouTube stream extraction |\n| pylast | Last.fm scrobbling |\n| readchar | Keyboard input |\n| rich | Terminal UI |\n| httpx | HTTP client with SOCKS |\n\n## Troubleshooting\n\n### Spotify showing \"via YouTube fallback\"\n\nspotifyd/librespot is not running or not detected. Start it:\n\n```bash\nsystemctl --user start spotifyd\n```\n\n### Pandora \"not available in this country\"\n\nTor might have selected a non-US exit node. OmniShuffle retries automatically, but you can also:\n\n```bash\n# Check your Tor exit IP\ncurl --socks5 127.0.0.1:9050 https://ipinfo.io/country\n```\n\n### mpv fails to load (`Symbol not found: _av_base64_encode`)\n\nmpv and ffmpeg are out of sync after a Homebrew update. Rebuild mpv:\n\n```bash\nbrew reinstall mpv\n```\n\n### No audio output\n\nVerify mpv is working:\n\n```bash\nmpv --no-video \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"\n```\n\n### Re-authorizing Spotify\n\nIf you need new scopes (e.g., after updating OmniShuffle):\n\n```bash\nrm ~/.config/omnishuffle/spotify_cache\nomnishuffle\n```\n\n## License\n\nMIT License. See [LICENSE](LICENSE) for details.\n\n## Acknowledgments\n\n- [pianobar](https://github.com/PromyLOPh/pianobar) for the inspiration\n- [spotifyd](https://github.com/Spotifyd/spotifyd) for Spotify Connect\n- All the API library maintainers\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frollecode%2Fomnishuffle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frollecode%2Fomnishuffle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frollecode%2Fomnishuffle/lists"}