guillevc/yubal
PythonSelf-hosted YouTube Music downloader. Tags, organizes, and keeps playlists in sync.
pip install yubalyubal
Self-hosted YouTube Music downloader. Paste a link, get a tagged, organized library.
Scheduled sync. Smart deduplication. Media server ready. Browser extension included.
📖 How It Works
Downloading music is easy. Organizing it is the hard part.
yubal takes a YouTube Music URL and produces a clean, tagged music library:
data/
├── Pink Floyd/
│ └── 1973 - The Dark Side of the Moon/
│ ├── 01 - Speak to Me.opus
│ ├── 01 - Speak to Me.lrc
│ ├── 02 - Breathe.opus
│ ├── 02 - Breathe.lrc
│ └── cover.jpg
│
├── Radiohead/
│ └── 1997 - OK Computer/
│ ├── 01 - Airbag.opus
│ ├── 01 - Airbag.lrc
│ ├── 02 - Paranoid Android.opus
│ ├── 02 - Paranoid Android.lrc
│ └── cover.jpg
│
└── _Playlists/
├── My Favorites [n2g-XhDv].m3u
└── My Favorites [n2g-XhDv].jpg
When downloading a playlist, each track lives in its album folder; the M3U file references it:
#EXTM3U
#EXTINF:239,Pink Floyd - Breathe
../Pink Floyd/1973 - The Dark Side of the Moon/02 - Breathe.opus
#EXTINF:386,Radiohead - Paranoid Android
../Radiohead/1997 - OK Computer/02 - Paranoid Android.opus
✨ Features
- Web UI — Real-time progress, job queue, works on mobile
- Albums, playlists & tracks — Paste any YouTube Music link, get organized files
- Scheduled sync — Subscribe to playlists; new tracks appear in your library automatically
- Smart deduplication — Same track across 10 playlists? Stored once, referenced everywhere
- Reliable downloads — Automatic retry on failures, graceful cancellation
- Automatic lyrics — Synced
.lrcfiles for karaoke-style playback in supported players - ReplayGain tagging — Track gain for consistent volume; album gain when downloading complete albums
- Format options —
opus(best quality/size), mp3, or m4a — direct download when available, transcoded otherwise - Media server ready — Tested with Navidrome, Jellyfin, and Gonic
- CLI — Download and inspect metadata from the terminal
🧩 Browser Extension
Download tracks and subscribe to playlists directly from YouTube and YouTube Music without leaving the page.
More info in the extension's README.md.
🚀 Quick Start
# compose.yaml
services:
yubal:
image: ghcr.io/guillevc/yubal:latest
container_name: yubal
ports:
- 8000:8000
environment:
PUID: 1000
PGID: 1000
YUBAL_SCHEDULER_CRON: "0 0 * * *"
YUBAL_DOWNLOAD_UGC: false
YUBAL_TZ: UTC
volumes:
- ./data:/app/data
- ./config:/app/config
restart: unless-stopped
[!TIP] Volume permissions: Set
PUID/PGIDto match your host user (runidto check). This also ensures compatibility with podman rootless. If/app/datais an NFS/Unraid mount that does not allowchown, make sure it is already writable by the configuredPUID/PGID.
docker compose up -d
# Open http://localhost:8000
Unraid? Use the community Docker template by @SerpentDrago (unraid forum thread).
⚙️ Configuration
| Variable | Description | Default (Docker) |
|---|---|---|
PUID |
User ID for file ownership | 1000 |
PGID |
Group ID for file ownership | 1000 |
YUBAL_AUDIO_FORMAT |
opus, mp3, or m4a |
opus |
YUBAL_AUDIO_QUALITY |
Transcode quality (0=best, 10=worst) | 0 |
YUBAL_SCHEDULER_ENABLED |
Enable automatic scheduled sync | true |
YUBAL_SCHEDULER_CRON |
Cron schedule for auto-sync | 0 0 * * * |
YUBAL_FETCH_LYRICS |
Fetch lyrics from lrclib.net | true |
YUBAL_YTMUSIC_LYRICS_FALLBACK |
Fall back to YouTube Music lyrics on lrclib miss | true |
YUBAL_DOWNLOAD_UGC |
Download user-generated content to _Unofficial/ |
false |
YUBAL_REPLAYGAIN |
Apply track gain; album gain for complete albums | true |
YUBAL_JOB_TIMEOUT_SECONDS |
Job execution timeout in seconds | 1800 |
YUBAL_BASE_PATH |
URL base path for reverse proxy subfolder | — |
YUBAL_TZ |
Timezone (IANA format) | UTC |
All options
| Variable | Description | Default (Docker) |
|---|---|---|
YUBAL_HOST |
Server bind address | 127.0.0.1 |
YUBAL_PORT |
Server port | 8000 |
YUBAL_DATA |
Music library output | /app/data |
YUBAL_CONFIG |
Config directory | /app/config |
YUBAL_LOG_LEVEL |
DEBUG, INFO, WARNING, ERROR |
INFO |
YUBAL_ASCII_FILENAMES |
Transliterate unicode to ASCII | false |
YUBAL_CORS_ORIGINS |
Allowed CORS origins | ["*"] |
YUBAL_TEMP |
Temp directory | System temp |
🔌 Media Server Integration
Tested with Navidrome, Jellyfin, and Gonic. Artists link correctly, even on tracks with multiple artists.
| Server | Artist linking | Playlists |
|---|---|---|
| Navidrome | ✅ Works out of the box | ✅ |
| Jellyfin | ⚙️ Enable "Use non-standard artists tags" in library settings | ✅ |
| Gonic | ⚙️ Set GONIC_MULTI_VALUE_ARTIST=multi |
❌ |
✅ Supported · ⚙️ Requires configuration · ❌ Not supported
[!TIP] Recommended stack: yubal + Navidrome gives you a self-hosted music streaming setup. Add a client like Symfonium (Android), Amperfy or Arpeggi (iOS), or Supersonic (desktop) to listen anywhere.
Detailed setup guides
Navidrome
No configuration required. Optionally, make imported playlists public:
ND_DEFAULTPLAYLISTPUBLICVISIBILITY=true
See Navidrome docs.
Jellyfin
For multi-artist support:
- Dashboard → Libraries → Music Library → Manage Library
- Check Use non-standard artists tags
- Save and rescan
Gonic
For artist linking:
GONIC_MULTI_VALUE_ARTIST=multi
GONIC_MULTI_VALUE_ALBUM_ARTIST=multi
M3U playlists are not supported (pending PR).
🍪 Cookies (Optional)
Need age-restricted content, private playlists, your Liked Music (list=LM), or Premium quality? Add your cookies:
- Export
https://www.youtube.com/cookies with a browser extension (yt-dlp guide) - Place at
config/ytdlp/cookies.txtor upload via the web UI
[!CAUTION] Cookie usage may trigger stricter rate limiting and could put your account at risk. See #3 and yt-dlp wiki.
🗺️ Roadmap
- Flat folder mode
- Post-download webhooks
- New music automatic discovery
- Browser extension (v0.7.0)
- UGC tracks — remixes, unofficial content (v0.5.0)
- Auto-sync playlists (v0.4.0)
- Automatic lyrics (.lrc) (v0.3.0)
- Single track downloads (v0.3.0)
- Playlist support with M3U generation (v0.2.0)
💜 Support
yubal is free, open-source, and built by one person. If it saves you time, consider supporting development:
A ⭐ also helps others find the project!
📈 Star History
🙏 Acknowledgments
Built with yt-dlp and ytmusicapi.
Thanks to everyone who's starred, shared, reported bugs, suggested features, or supported the project 💝
License
For personal archiving only. Comply with YouTube's Terms of Service and applicable copyright laws.