https://github.com/guillevc/yubal
YouTube Music album downloader with Spotify metadata auto-tagging
https://github.com/guillevc/yubal
Last synced: 4 months ago
JSON representation
YouTube Music album downloader with Spotify metadata auto-tagging
- Host: GitHub
- URL: https://github.com/guillevc/yubal
- Owner: guillevc
- License: mit
- Created: 2025-12-29T14:14:08.000Z (6 months ago)
- Default Branch: master
- Last Pushed: 2026-01-09T01:45:42.000Z (5 months ago)
- Last Synced: 2026-01-12T17:21:36.238Z (5 months ago)
- Language: Python
- Homepage:
- Size: 6.8 MB
- Stars: 266
- Watchers: 0
- Forks: 4
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
- awesome-github-repos - guillevc/yubal - Self-hosted YouTube Music downloader. Tags, organizes, and keeps playlists in sync. (Python)
README
# yubal
**Self-hosted YouTube Music downloader with automatic metadata tagging and playlist sync.**
Paste a link, get a properly tagged and organized library. Subscribe to playlists to keep them synced. Albums sorted by artist and year. No duplicates. Media server ready.
[](https://github.com/guillevc/yubal/actions/workflows/ci.yaml)
[](https://github.com/guillevc/yubal/releases)
[](https://ghcr.io/guillevc/yubal)
[](https://codecov.io/gh/guillevc/yubal)

> [!IMPORTANT]
> **Upgrading from v0.3?** Folder and file names now preserve unicode characters (`Bjork` β `BjΓΆrk`), which may create duplicates alongside existing ASCII-named items.
>
> To keep the previous ASCII behavior, set `YUBAL_ASCII_FILENAMES=true`. Otherwise, check your library and merge any duplicates after upgrading.
## π 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 goes to its album folderβthe M3U file just references them:
```m3u
#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, responsive design
- **Albums, playlists & tracks** β Paste any YouTube Music link, get organized files
- **Scheduled sync** β Subscribe to playlists; new tracks download automatically
- **Smart deduplication** β Same track across 10 playlists? Stored once, referenced everywhere
- **Reliable downloads** β Automatic retry on failures, graceful cancellation
- **Automatic lyrics** β Synced `.lrc` files downloaded alongside tracks when available
- **ReplayGain tagging** β Track and album ReplayGain/R128 tags for consistent playback volume
- **Format options** β Native `opus` (best quality), mp3, or m4a (direct download when available, transcoded otherwise)
- **Media server ready** β Tested with [Navidrome, Jellyfin, and Gonic](#-media-server-integration)
- **[CLI](packages/yubal/src/yubal/cli/README.md)** β Download and inspect metadata from the terminal
## π Quick Start
```yaml
# compose.yaml
services:
yubal:
image: ghcr.io/guillevc/yubal:latest
container_name: yubal
user: 1000:1000
ports:
- 8000:8000
environment:
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:** The container runs as UID:GID `1000:1000` by default. If your host user has a different UID, either:
>
> - Change `user:` to match your UID:GID (run `id` to check), or
> - Set ownership on the volume directories: `chown 1000:1000 -R data config`
```bash
docker compose up -d
# Open http://localhost:8000
```
> **Unraid?** Use the [community Docker template](https://github.com/SerpentDrago/UnraidDockerTemplates/tree/main/yubal) by [@SerpentDrago](https://github.com/SerpentDrago) ([unraid forum thread](https://forums.unraid.net/topic/197157-support-yubal-self-hosted-youtube-music-downloader/)).
## βοΈ Configuration
| Variable | Description | Default (Docker) |
| --------------------------- | ------------------------------------------------- | ---------------- |
| `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_DOWNLOAD_UGC` | Download user-generated content to `_Unofficial/` | `false` |
| `YUBAL_REPLAYGAIN` | Apply ReplayGain tags to downloads | `true` |
| `YUBAL_JOB_TIMEOUT_SECONDS` | Job execution timeout in seconds | `1800` |
| `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
Detailed setup guides
### Navidrome
No configuration required. Optionally, make imported playlists public:
```bash
ND_DEFAULTPLAYLISTPUBLICVISIBILITY=true
```
See [Navidrome docs](https://www.navidrome.org/docs/usage/configuration/options/).
### Jellyfin
For multi-artist support:
1. **Dashboard β Libraries β Music Library β Manage Library**
2. Check **Use non-standard artists tags**
3. Save and rescan
### Gonic
For artist linking:
```bash
GONIC_MULTI_VALUE_ARTIST=multi
GONIC_MULTI_VALUE_ALBUM_ARTIST=multi
```
M3U playlists are not supported ([pending PR](https://github.com/sentriz/gonic/pull/537)).
## πͺ Cookies (Optional)
Need age-restricted content, private playlists, or Premium quality? Add your cookies:
1. Export `https://www.youtube.com/` cookies with a browser extension ([yt-dlp guide](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp))
2. Place at `config/ytdlp/cookies.txt` or upload via the web UI
> [!CAUTION]
> Cookie usage may trigger stricter rate limiting and could put your account at risk. See [#3](https://github.com/guillevc/yubal/issues/3) and [yt-dlp wiki](https://github.com/yt-dlp/yt-dlp/wiki/Extractors#youtube).
## πΊοΈ What's Coming
- [x] Playlist support with M3U generation ([v0.2.0](https://github.com/guillevc/yubal/releases/tag/v0.2.0))
- [x] Single track downloads ([v0.3.0](https://github.com/guillevc/yubal/releases/tag/v0.3.0))
- [x] Automatic lyrics (.lrc) ([v0.3.0](https://github.com/guillevc/yubal/releases/tag/v0.3.0))
- [x] Auto-sync playlists ([v0.4.0](https://github.com/guillevc/yubal/releases/tag/v0.4.0))
- [x] UGC tracks (user-generated content, remixes, unofficial tracks) ([v0.5.0](https://github.com/guillevc/yubal/releases/tag/v0.5.0))
- [ ] Flat folder mode
- [ ] Browser extension
- [ ] Post-download webhooks
- [ ] New music automatic discovery
## π Support
If yubal is useful to you, consider supporting its development:
[](https://ko-fi.com/guillevc) [](https://github.com/sponsors/guillevc)
A β also helps others discover yubal!
## π Star History
[](https://star-history.com/#guillevc/yubal&Date)
## π Acknowledgments
Built with [yt-dlp](https://github.com/yt-dlp/yt-dlp) and [ytmusicapi](https://github.com/sigma67/ytmusicapi).
Thanks to everyone who's starred, shared, reported bugs, suggested features, or [supported the project](https://ko-fi.com/guillevc) π
## License
[MIT](LICENSE)
---
For personal archiving only. Comply with YouTube's Terms of Service and applicable copyright laws.