Skip to main content

Download Spotify tracks/albums with metadata via YouTube Music (Perfect for Jellyfin libraries!)

Project description

SpotifySaver ๐ŸŽตโœจ

Python PyPI Version Docker GitHub Container Registry FFmpeg yt-dlp YouTube Music Spotify License: MIT Code style: black Ask DeepWiki

โš ๏ธThis repository is under a strong stage of development, expect constant changes. If you find any mistake or bug, please open an ISSUE.

All-in-one tool for downloading and organizing music with Spotify metadata for Jellyfin.

The app connects to the Spotify and YouTube Music APIs. The goal is to generate an .nfo XML file to complete the metadata required by Jellyfin when building music libraries.

Read this file in Spanish

๐ŸŒŸ Features

  • โœ… Download audio from YouTube Music with Spotify metadata
  • โœ… Synchronized lyrics (.lrc) from LRC Lib
  • โœ… Generation of Jellyfin-compatible .info files (Still some things to work on here! โš ๏ธ)
  • โœ… Automatic folder structure (Artist/Album)
  • โœ… Command-line interface (CLI)
  • โœ… Web interface (UI) with real-time progress
  • โœ… RESTful API for integrations
  • โœ… Docker support with auto-builds
  • โœ… Playlist support
  • โœ… MP3 Conversion
  • โœ… Support for multiple bitrates (128, 180, 220, etc.)

Requirements

# Installation with Poetry (recommended)
git clone https://github.com/gabrielbaute/spotify-saver.git
cd spotify-saver
poetry install

# Or with pip
pip install git+https://github.com/gabrielbaute/spotify-saver.git

โš ๏ธ IMPORTANT: You must log in to your Spotify account as a developer, create an app, and obtain a "client id" and "client secret." You must place this information in an .env file in the project's root directory.

โš™๏ธ Configuration

Once in your project directory, run:

spotifysaver init

This will create a local .env file with the environment variables that will be requested:

Variable Description Default Value
SPOTIFY_CLIENT_ID ID of the Spotify app you created -
SPOTIFY_CLIENT_SECRET Secret key generated for your Spotify app -
SPOTIFY_REDIRECT_URI Spotify API Validation URI http://localhost:8888/callback
SPOTIFYSAVER_OUTPUT_DIR Custom directory path (optional) ./Music
YTDLP_COOKIES_PATH Cookie file path (optional) -
API_PORT API server port (optional) 8000
API_HOST Host for the API (optional) 0.0.0.0

The variable YTDLP_COOKIES_PATH will indicate the location of the file with the Youtube Music cookies, in case we have problems with restrictions to yt-dlp, specifically it is for cases in which youtube blocks the app for "behaving like a bot" (which is not entirely false lol)

You can also check the .example.env file

๐Ÿ“š Documentation

We maintain a documentation with Deepwiki, which constantly tree the repository. You can consult it at all times.

The documentation for using the API, on the other hand, can be found in this same repository here: API Documentation

๐Ÿ’ป Using the CLI

Available Commands

Command Description Example
init Configure environment variables spotifysaver init"
download [URL] Download track/album from Spotify spotifysaver download "URL_SPOTIFY"
inspect Shows Spotify metadata (album, playlist) spotifysaver inspect "URL_SPOTIFY"
show-log Shows the application log spotifysaver show-log
version Shows the installed version spotifysaver version

Download Options

Option Description Accepted Values โ€‹โ€‹
--lyrics Download synchronized lyrics (.lrc) Flag (no value)
--output DIR Output directory Valid path
--format FORMAT Audio format m4a (default), mp3
--cover Saves the cover album in de directoy (.jpg) Flag (no value)
--nfo Generates a .nfo metadata file in the JellyFin format Flag (no value)
--explain Show score breakdown for each track without downloading (for error analysis) Flag (no value)
--dry-run Simulate download without saving files Flag (no value)

show-log Options

Option Description Accepted Values โ€‹โ€‹
--lines Number of log lines to display --lines 25 --> int
--level Filter by log level INFO, WARNING, DEBUG, ERROR
--path Displays the location of the log file Flag (no value)

๐Ÿ’ก Usage Examples

# Set spotifysaver configuration
spotifysaver init

# Download album with synchronized lyrics
spotifysaver download "https://open.spotify.com/album/..." --lyrics

# Download album with album cover and metadata file
spotifysaver download "https://open.spotify.com/album/..." --nfo --cover

# Download song in MP3 format
spotifysaver download "https://open.spotify.com/track/..." --format mp3

Usage with API

To use the API, you need to have the API server running. You can start it with the following command:

# Start the API server
spotifysaver-api

The server will run at http://localhost:8000 by default. You can find the API documentation here, which describes the technical aspects and usage in detail.

๐Ÿ–ฅ๏ธ Web Interface (UI)

SpotifySaver now includes a modern web interface that makes it easy to download music without using the command line:

# Start the web interface (includes API server)
spotifysaver-ui

This will start both the API server and a web interface that you can access at http://localhost:3000. The web interface provides:

  • Easy URL input: Simply paste any Spotify URL (track, album, or playlist)
  • Full configuration: All download options available through an intuitive interface
  • Real-time progress: Monitor download progress and see detailed logs
  • Responsive design: Works on desktop and mobile devices
  • Automatic browser opening: Opens your default browser automatically

Web Interface Features:

  • โœ… URL validation for Spotify links
  • โœ… Configurable audio format (M4A/MP3) and bitrate
  • โœ… Toggle lyrics and NFO file generation
  • โœ… Custom output directory
  • โœ… Real-time download progress
  • โœ… Activity log with timestamps
  • โœ… Error handling and user feedback

Default Ports:

  • Web Interface: http://localhost:3000
  • API Endpoint: http://localhost:8000

๐Ÿณ Docker Support

SpotifySaver is available as a Docker container with full web interface support. Choose between GitHub Container Registry or building locally.

๐Ÿš€ Quick Start with Docker Compose

  1. Create configuration files:
# Create directories
mkdir -p music config

# Create environment file
cat > .env << EOF
SPOTIFY_CLIENT_ID=your_client_id_here
SPOTIFY_CLIENT_SECRET=your_client_secret_here
SPOTIFY_REDIRECT_URI=http://localhost:8000/callback
EOF
  1. Run with Docker Compose:
# Using pre-built image from GitHub Registry
docker compose up -d

# Or build locally
docker compose up --build
  1. Access the web interface:

๐Ÿ“ฆ Using GitHub Container Registry

Pull and run directly:

# Pull latest version
docker pull ghcr.io/gabrielbaute/spotify-saver:latest

# Run container
docker run -d \
  --name spotifysaver \
  -p 3000:3000 \
  -p 8000:8000 \
  -v ./music:/music \
  -v ./config:/config \
  -e SPOTIFY_CLIENT_ID=your_client_id \
  -e SPOTIFY_CLIENT_SECRET=your_client_secret \
  ghcr.io/gabrielbaute/spotify-saver:latest

Available tags:

  • latest - Latest stable release
  • 0.6.3-test-2 - Specific version
  • 0.6 - Major.minor version

๐Ÿ”ง Environment Variables

Variable Description Default
SPOTIFY_CLIENT_ID Spotify API Client ID Required
SPOTIFY_CLIENT_SECRET Spotify API Client Secret Required
SPOTIFY_REDIRECT_URI Callback URL http://localhost:8000/callback
UI_PORT Web interface port 3000
API_PORT API server port 8000
MUSIC_DIR Host music directory ./music
CONFIG_DIR Host config directory ./config
LOG_LEVEL Logging level INFO

๐Ÿ› ๏ธ Custom Docker Compose Configuration

services:
  spotifysaver:
    container_name: spotifysaver
    image: ghcr.io/gabrielbaute/spotify-saver:latest
    ports:
      - "${UI_PORT:-3000}:3000"
      - "${API_PORT:-8000}:8000"
    environment:
      - SPOTIFY_CLIENT_ID=${SPOTIFY_CLIENT_ID}
      - SPOTIFY_CLIENT_SECRET=${SPOTIFY_CLIENT_SECRET}
      - SPOTIFY_REDIRECT_URI=${SPOTIFY_REDIRECT_URI:-http://localhost:8000/callback}
      - SPOTIFYSAVER_LOG_LEVEL=${LOG_LEVEL:-INFO}
    volumes:
      - ${MUSIC_DIR:-./music}:/music
      - ${CONFIG_DIR:-./config}:/config
      - spotifysaver_logs:/logs
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

volumes:
  spotifysaver_logs:

๐Ÿ”จ Building Locally

# Clone repository
git clone https://github.com/gabrielbaute/spotify-saver.git
cd spotify-saver

# Build image
docker build -t spotify-saver .

# Run container
docker run -d \
  --name spotifysaver \
  -p 3000:3000 \
  -p 8000:8000 \
  -v ./music:/music \
  -v ./config:/config \
  -e SPOTIFY_CLIENT_ID=your_client_id \
  -e SPOTIFY_CLIENT_SECRET=your_client_secret \
  spotify-saver

๐Ÿ“‚ Output Structure

Music/
โ”œโ”€โ”€ Artist/
โ”‚ โ”œโ”€โ”€ Album (Year)/
โ”‚ โ”‚ โ”œโ”€โ”€ 01 - Song.m4a
โ”‚ โ”‚ โ”œโ”€โ”€ 01 - Song.lrc
โ”‚ โ”‚ โ”œโ”€โ”€ album.nfo
โ”‚ โ”‚ โ””โ”€โ”€ cover.jpg
โ”‚ โ””โ”€โ”€ artist_info.nfo

๐Ÿค Contributions

  1. Fork the project
  2. Create your branch (git checkout -b feature/new-feature)
  3. Commit your changes (git commit -m 'Add awesome feature')
  4. Push to the branch (git push origin feature/new-feature)
  5. Open a Pull Request

๐Ÿ“„ License

MIT ยฉ TGabriel Baute

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spotifysaver-0.7.3.tar.gz (70.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spotifysaver-0.7.3-py3-none-any.whl (109.8 kB view details)

Uploaded Python 3

File details

Details for the file spotifysaver-0.7.3.tar.gz.

File metadata

  • Download URL: spotifysaver-0.7.3.tar.gz
  • Upload date:
  • Size: 70.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for spotifysaver-0.7.3.tar.gz
Algorithm Hash digest
SHA256 43826508f330a534c41a8a097d5701c361d0fa6823aa28fd1b1ba33445b17cd6
MD5 1c1bc074c6aa0183524bd16f755f82d4
BLAKE2b-256 fad5012ef7a24b3b73dcef89750741dfb02ba70bc8d5322fbb1baaf95c65edd8

See more details on using hashes here.

File details

Details for the file spotifysaver-0.7.3-py3-none-any.whl.

File metadata

  • Download URL: spotifysaver-0.7.3-py3-none-any.whl
  • Upload date:
  • Size: 109.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for spotifysaver-0.7.3-py3-none-any.whl
Algorithm Hash digest
SHA256 118f2eecb23f36695eaea476d7c2ed77a1e2a61f191d8be6dec59a144d25e5e5
MD5 03977e796420c3c5068b0e6f403acddd
BLAKE2b-256 bb4c89f937259fd8ef0b12fb17f9c75740cf13e92f144b35e221b6c6141b1d46

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page