Skip to main content

Synchronized lyrics in your terminal for the currently playing Spotify track

Project description

spotty

Synchronized lyrics in your terminal for the currently playing Spotify track.

  • Line-by-line sync using LRC timestamps from lrclib.net
  • Falls back to plain lyrics via lyrics.ovh if no synced lyrics found
  • Smooth display — progress interpolated between API polls (no jumping)
  • Auto-refreshes when track changes
  • Shows lyrics source (lrclib or lyrics.ovh) as a dim footer
  • Handles instrumental sections, multi-artist tracks, featured artists
  • Live offset calibration: press [ / ] during playback to shift lyrics 100ms earlier/later; persisted per-track

spotty demo

Requirements

Installation

pip install spotty-cli

Or from source:

git clone https://github.com/Arideno/spotty
cd spotty
pip install -e .

Setup

1. Create a Spotify App

  1. Go to Spotify Developer Dashboard
  2. Click Create app
  3. Set Redirect URI to http://127.0.0.1:8888/callback
  4. Copy your Client ID

2. Configure credentials

spotty init

You will be prompted for:

Spotify Client ID: <paste your client ID>
Redirect URI [http://127.0.0.1:8888/callback]: <Enter to keep default>

Config is saved to ~/.config/spotty/config.json.

On first run after init, a browser window opens for Spotify authorization. Tokens are saved to ~/.config/spotty/tokens.json and refreshed automatically.

Usage

# Synchronized mode (default) — live updating display
spotty

# Plain lyrics — print and exit
spotty --plain

# Adjust timing if lyrics feel early or late
spotty --offset 300    # shift 300ms later
spotty --offset -200   # shift 200ms earlier

# Bypass cache for one run
spotty --no-cache

# During synchronized playback, adjust timing live
#   [   shift lyrics 100ms earlier
#   ]   shift lyrics 100ms later
# Offset is saved per-track and shown in the progress bar (+200ms or dim [ / ] hint)

# Version
spotty --version

# Help
spotty --help

Options

Option Default Description
--plain off Show plain (non-synced) lyrics and exit
--offset MS 0 Shift lyrics by MS milliseconds. Positive = later, negative = earlier
--no-cache off Bypass the lyrics cache for this run
--version Show version and exit
--help Show help and exit

Configuration

Credentials are stored in ~/.config/spotty/config.json after running spotty init.

Key Required Default Description
client_id Yes Spotify app client ID
redirect_uri No http://127.0.0.1:8888/callback OAuth callback URI — must match your Spotify app settings
cache_dir No ~/.cache/spotty Override lyrics cache directory
cache_enabled No true Set to false to permanently disable the lyrics cache

To update any value, re-run spotty init.

File locations

File Purpose
~/.config/spotty/config.json Credentials (also accepts optional cache_dir)
~/.config/spotty/tokens.json OAuth tokens (auto-managed)
~/.cache/spotty/lyrics.db SQLite lyrics cache and per-track offset calibrations (auto-managed, 30-day TTL)

Delete tokens.json to force re-authentication.

How it works

  1. Auth — OAuth2 PKCE flow, no client secret needed in the token exchange
  2. Now playing — polls GET /me/player/currently-playing every 500ms
  3. Lyrics — checks SQLite cache first (~/.cache/spotty/lyrics.db, 30-day TTL); on miss fetches from lrclib.net and lyrics.ovh in parallel, then stores the result. Per-track offset calibrations are loaded from the same cache on each track change and written back on each [/] press.
  4. Display — interpolates playback position between polls using the local clock for smooth highlighting

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run directly
python -m spotty.cli

Contributing

  1. Fork the repo
  2. Create a branch: git checkout -b my-feature
  3. Make changes and add tests
  4. Run pytest — all tests must pass
  5. Open a pull request

License

MIT — see LICENSE

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

spotty_cli-0.0.8.tar.gz (227.3 kB view details)

Uploaded Source

Built Distribution

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

spotty_cli-0.0.8-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

Details for the file spotty_cli-0.0.8.tar.gz.

File metadata

  • Download URL: spotty_cli-0.0.8.tar.gz
  • Upload date:
  • Size: 227.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for spotty_cli-0.0.8.tar.gz
Algorithm Hash digest
SHA256 2f8796b9dfb60bd6d30a3799519f7fed8d8ff3def138f16cc6e6314ab34fa34c
MD5 3a18b8de004307af2454039f10f2573d
BLAKE2b-256 316f0d4e6f467a9310a9c9b497e85a52bccd38c8014d1a0a4791d2c622e96f75

See more details on using hashes here.

Provenance

The following attestation bundles were made for spotty_cli-0.0.8.tar.gz:

Publisher: release.yml on Arideno/spotty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spotty_cli-0.0.8-py3-none-any.whl.

File metadata

  • Download URL: spotty_cli-0.0.8-py3-none-any.whl
  • Upload date:
  • Size: 14.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for spotty_cli-0.0.8-py3-none-any.whl
Algorithm Hash digest
SHA256 52599daaa8fb1a11bc8a5544801e512f043955065529a7c05f34d273e76af8d4
MD5 2559be7dd2432e9107e7b4ae65e8c1bf
BLAKE2b-256 b22892493d72eec2ad56d91c50eff1b9ebd32ea5534dbd474de450a44028063e

See more details on using hashes here.

Provenance

The following attestation bundles were made for spotty_cli-0.0.8-py3-none-any.whl:

Publisher: release.yml on Arideno/spotty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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