mirror of
https://github.com/Felitendo/spotifast.git
synced 2026-11-01 17:33:26 +01:00
README, Getting started and the translating guide now say that the interface follows the system language, how Settings > Appearance > Language overrides it, which catalogue a regional system language uses, and that Spanish is complete while the other catalogues fall back to English. The settings reference lists the "language" field and --demo-language.
660 lines
35 KiB
Markdown
660 lines
35 KiB
Markdown
# Spotifast
|
||
|
||
Previously **Fastpotify**. Same native Spotify client, now at
|
||
[spotifast.rocks](https://spotifast.rocks/). The new name starts with version 0.8.0;
|
||
your existing settings and sign-ins carry over, except when
|
||
[switching the Flatpak installation](docs/_reference/renaming.md#flatpak).
|
||
|
||
**Spotify, native and fast.** Spotifast is a Spotify client written in
|
||
Rust with [egui](https://github.com/emilk/egui). It plays music through
|
||
[librespot](https://github.com/librespot-org/librespot). It typically uses
|
||
100–250 MB of RAM, while Spotify's desktop app often uses 600 MB to over 1 GB.
|
||
It runs on Linux, macOS, and Windows, starts in well under a second, and has no
|
||
browser engine.
|
||
|
||
**Playback needs Spotify Premium.** Free accounts can browse and search, but
|
||
cannot play music through Spotifast on this computer or another device.
|
||
|
||

|
||
|
||
See [spotifast.rocks](https://spotifast.rocks/) for installation, setup,
|
||
everyday use, and connection details.
|
||
|
||
`spotifast` is the main command and `fastpotify` remains available
|
||
for existing scripts. Starting with 0.9.1, the existing profile and protected
|
||
sign-ins migrate to Spotifast's names. Existing destination profiles are preserved.
|
||
AUR and Homebrew packages now use the Spotifast name. See [rename compatibility](docs/_reference/renaming.md).
|
||
|
||
## What it does
|
||
|
||
- **Plays music on this computer.** Spotifast appears as a Spotify Connect
|
||
device. Select it from your phone or play music in the app. Playback is
|
||
gapless and supports up to 320 kbps, with
|
||
optional volume normalisation and an on-disk audio cache.
|
||
Stalled Spotify connections time out after five seconds per attempt so
|
||
playback can try another endpoint.
|
||
Since 0.8.0, a confirmed local seek discards audio queued from
|
||
the old position. Decoder, download, and device-buffer delays can still apply.
|
||
Starting a sorted playlist or Liked Songs view shows the requested song
|
||
immediately while playback connects, using its loaded metadata (available since 0.8.0). Sorted views start at their first playable row. Filtering a
|
||
playlist or Liked Songs keeps playback within the shown songs and preserves
|
||
repeated songs; Play is unavailable when no shown song can play.
|
||
- **Controls other devices.** Move playback to a speaker, a phone, or
|
||
another computer from the device picker, and keep controlling it: play,
|
||
pause, skip, seek, shuffle, repeat, volume. The picker expands upward to
|
||
show several devices at once, fitting the window; longer lists scroll.
|
||
On `main`, after 0.8.0, switching back to this computer transfers the active
|
||
Connect session with its song, position, queue, and paused or playing state.
|
||
- **Finds speakers on your network.** Spotifast finds librespot, spotifyd,
|
||
and supported hardware receivers over mDNS. Once connected, they appear as
|
||
Spotify Connect devices. The picker uses responding receivers' names and
|
||
combines entries with the same device ID.
|
||
- **Library.** Browse playlists, Liked Songs, saved albums, followed artists,
|
||
podcasts, and saved episodes. Filter, pin, and reorder sidebar items.
|
||
On `main`, after 0.9.1, the Library header switches between a list and a
|
||
responsive cover grid.
|
||
On `main`, after 0.9.1, with local playback enabled, audiobooks saved in
|
||
Spotify stay out of Podcasts, since they can't be played here.
|
||
Since 0.8.0, double-click a playlist row in Library to start playback;
|
||
a single click opens it. In the grid, a card's corner button plays it.
|
||
Settings offers a compact track list with one line per song and spaced
|
||
separators between its name, artists and added date.
|
||
Since 0.8.0, choose name, recent plays, or saved-date order where
|
||
available. Follow Spotify’s playlist order or keep a separate local arrangement.
|
||
Spotify doesn't let apps change its order, so on `main`, after 0.9.1,
|
||
dragging a playlist while following it switches to the local arrangement
|
||
and says so.
|
||
Move Liked Songs among your pins or unpin it and choose its local position;
|
||
the placement survives restarts.
|
||
With local playback enabled, releases that the Web API groups as singles
|
||
are labelled EP when librespot confirms that type.
|
||
Liked Songs reopens from an account-specific metadata cache. Older rows
|
||
refresh in the background while Like and Unlike take effect immediately.
|
||
Right-click album, artist, and podcast cards for their actions (available since 0.8.0).
|
||
- **Search** across songs, artists, albums, playlists, podcasts, and episodes,
|
||
with a top result and per-type views. Right-click results and cards for their actions.
|
||
When Spotify provides an artist profile, its name on a song opens that page,
|
||
including from the top result.
|
||
Text fields offer Cut, Copy, Paste and Select all from their right-click menu.
|
||
Since 0.8.0, a personal app searches the catalogue while shared
|
||
access finds playlists. Each part appears independently, even if the other fails.
|
||
|
||
Since 0.8.0, the search field stays clear of the device and update
|
||
badges in narrow windows; hover their icons to read the labels.
|
||
- **Home** with Made for you, Recently played, your top artists and songs, and
|
||
recommendations. Right-click playlist shortcuts and shelf cards for their actions.
|
||
On `main`, after 0.9.1, **Your podcasts** lists episodes of your saved
|
||
podcasts that you have started, then new ones you have not.
|
||
- **Artist pages** with popular songs, a filterable discography, and related
|
||
artists. **Album**, **playlist**, and **podcast** pages support playback
|
||
from any row. Since 0.8.0, album and playlist scrollbars represent the full track count;
|
||
dragging to an unloaded section fetches that section directly.
|
||
Discography and related-artist cards also have right-click menus (available since 0.8.0).
|
||
Artist names in the player bar open their pages, including during local
|
||
playback before Web API metadata arrives (available since 0.8.0).
|
||
On `main`, after 0.8.0, an album, single, or EP's **Add to queue** adds all
|
||
its playable songs in album order, on this computer or another device.
|
||
- **Radio.** On `main`, after 0.9.1, **Go to song radio** in a song's menu, and
|
||
**Go to playlist radio**, **Go to album radio**, or **Go to artist radio** in
|
||
their **…** menus, open a page of 50 songs Spotify picks to go with them.
|
||
**Play** plays exactly those songs, **Refresh** in **…** asks for a new mix,
|
||
and **Save as playlist** keeps the mix as a private playlist. Radio needs
|
||
playback on this computer to be set up.
|
||
- **Edit your playlists.** Create, rename, describe, reorder, and delete them.
|
||
Since 0.8.0, hold a dragged song near the playlist's top or bottom
|
||
edge to scroll to rows beyond the screen. The Library sidebar scrolls while
|
||
dragging toward offscreen playlists too.
|
||
On `main`, after 0.8.0, upload a JPEG or PNG cover from
|
||
**Edit details → Change cover**.
|
||
Add songs from a row menu, or drag a row or the currently playing song to a
|
||
playlist in the sidebar. Since 0.8.0, dragging a selected row
|
||
copies the whole selection in displayed order; the preview shows its count.
|
||
Drop the selection on Liked Songs to save every selected song. Selection
|
||
uses a translucent neutral highlight, without a row outline.
|
||
Drop a song from the player
|
||
bar, queue, or another list between rows of an open editable playlist to
|
||
insert it there. This adds a copy and leaves playback and the queue unchanged.
|
||
Clear the playlist’s filter and sort to choose an insertion position.
|
||
Drop it on an empty playlist to add its first song.
|
||
A playlist a friend shared with you takes songs too,
|
||
as Spotify's own apps allow. Filter the **Add to playlist** menu by name to
|
||
find the destination quickly. On `main`, after 0.8.0, playlist folders and
|
||
invitation permissions also load when the library finishes before local
|
||
playback connects.
|
||
- **Opens Spotify links.** Spotifast registers for `spotify:` links, so a
|
||
song, album, artist, playlist, or podcast shared from another app opens
|
||
in it, whether it is running or not. `open.spotify.com` addresses go
|
||
through the browser, which hands them to the same handler.
|
||
- **Queue** as a side panel or a page; it names what is playing from, and
|
||
anything can be added to it from a row menu. **Add to queue** places songs
|
||
after those already queued and before the context continues.
|
||
On other devices, rate-limited additions retry automatically after Spotify's
|
||
requested wait, preserving album and song order and their known details.
|
||
A permanent failure removes the rejected additions and reports the error.
|
||
Starting an album or playlist keeps those additions under **Playing next**,
|
||
even when it starts a song you also queued. **Clear queue** removes the
|
||
additions and keeps the playing collection's remaining songs.
|
||
Dropping a dragged song, or selection, on the player bar's Queue button
|
||
queues it the same way. While this computer is playing locally, dropping
|
||
a song at a position within the open queue's *Playing next* inserts it
|
||
there instead of always at the end, and dragging a queued row elsewhere in
|
||
that section reorders it; with a remote Spotify Connect device, every drop
|
||
still just adds to the end, since neither Spotify nor librespot can
|
||
reorder or insert into a live remote queue.
|
||
Selecting repeated playlist rows queues every occurrence in the selected
|
||
order. A repeated click counts once, and the notification counts actual additions.
|
||
Since 0.8.0, Recent keeps repeated short-song plays separate,
|
||
including consecutive local repeats of the same song.
|
||
Each Recent row starts the song it names and shows it in the player bar
|
||
immediately while playback starts.
|
||
- Since 0.8.0, a playlist's **Play** button explicitly starts at
|
||
its first available song when Shuffle is off and the original order is
|
||
selected. Double-click a row to start there; use the player bar to resume.
|
||
Cached playlists must match Spotify's revision and song count before their
|
||
rows can determine playback order. Pending playlist edits stay visible and
|
||
are saved to that cache only after all writes succeed.
|
||
Refresh waits for pending edits and their Spotify revision to be confirmed;
|
||
a failed refresh keeps the current rows and offers a retry.
|
||
Choose **Refresh** in a playlist's **…** menu to pick up changes made in
|
||
another Spotify client.
|
||
Large playlist checkpoints read and write their JSON through a small background
|
||
buffer, preserving the existing cache format without another full JSON copy.
|
||
- On `main`, after 0.9.1, the **Shuffle** button beside a collection's **Play**
|
||
button sets the global mode without starting that collection. Choose it before
|
||
a playback device is active; the next **Play** uses that selection. While
|
||
another collection plays, it changes that playback's mode without switching
|
||
to the viewed collection.
|
||
- **Lyrics.** Follow synced lyrics in a side panel or full-screen view, or read
|
||
unsynced lyrics when timestamps are unavailable. Full-screen lyrics scroll
|
||
smoothly and highlight the playing line automatically.
|
||
- **Resumes the last session.** On startup, the last song is paused where it
|
||
stopped. Play resumes it, and the other playback controls work before it
|
||
starts.
|
||
- **Album-art colour.** Pages and the player bar take a tint from the cover
|
||
of what you are looking at or listening to. The bar fades from one song's
|
||
colour to the next rather than switching in a single frame. Turn it off in
|
||
Settings.
|
||
- **Light and dark**, or follow the system.
|
||
- **Repeat stays selected.** On `main`, after 0.8.0, starting another song
|
||
locally preserves Repeat, with Shuffle on or off.
|
||
- **Song changes keep the selected song.** On `main`, after 0.9.1, the default
|
||
audio output keeps discarded audio paced while a replacement loads, preventing
|
||
the old cached song from racing to its end and causing an extra skip.
|
||
- **Reconnects keep the queue.** On `main`, after 0.8.0, recovering an
|
||
interrupted local playback session restores its playlist position,
|
||
queued songs, shuffle order, and Repeat mode.
|
||
- **Light and dark**, or follow the system.
|
||
- **Native window behaviour.** On macOS, double-click the top bar to use the
|
||
Fill, Zoom, Minimise or Do Nothing action selected in Desktop & Dock.
|
||
On `main`, after 0.9.1, buttons, rows and cards keep the ordinary arrow
|
||
pointer; only links, such as artist names, show the hand.
|
||
- **Winamp mini player.** `Ctrl+M` opens a small player for classic `.wsz`
|
||
skins, drawn at 1x to 4x scale. It includes a spectrum analyser, playlist,
|
||
and equalizer. It keeps its shade mode and, where the desktop permits,
|
||
its own position when switching views. Drop a skin from the
|
||
[Winamp Skin Museum](https://skins.webamp.org) on either window to add it.
|
||
On `main`, after 0.8.0, switching to the mini player preserves the main
|
||
window's size even if its native close takes another frame.
|
||
On Windows, on `main` after 0.9.1, the main window uses the standard
|
||
Windows title bar. **Settings → Appearance → Custom title bar** switches to
|
||
Spotifast's own title bar and window buttons.
|
||
On Windows, since 0.8.0, a mini player saved on a disconnected monitor
|
||
starts at a default position on the current desktop.
|
||
Clicking or double-clicking the Windows tray icon brings the window forward;
|
||
the tray menu still offers Show or hide.
|
||
On Windows, since 0.8.0, and in Linux X11 sessions, hide its taskbar button
|
||
from Settings or the mini player's options menu while keeping the window
|
||
and tray controls available.
|
||
On Wayland, use the desktop's Keep Above shortcut or rule; the app's
|
||
Always on top controls are unavailable there.
|
||
|
||

|
||
- **Equalizer.** Winamp's ten bands and presets over the music played on
|
||
this computer, in Settings and in the skin.
|
||
- **MilkDrop.** The visualiser, powered by
|
||
[projectM](https://github.com/projectM-visualizer/projectm), runs in its own
|
||
window and process. It supports fullscreen and automatically downloads more
|
||
than 10,000 `.milk` presets on first use (about 26 MB).
|
||
|
||
https://github.com/user-attachments/assets/12b31312-0e0c-4b34-9383-e8c66aabc58d
|
||
- **Keyboard-first.** Every common action has a shortcut (`Ctrl+/` or `?` lists
|
||
them).
|
||
- **Keeps playing when you close the window.** Spotifast stays in the system
|
||
tray. Use the tray icon or media controls to reopen it, and quit from the
|
||
tray menu or with `Ctrl+Q`. You can make the close button quit in Settings.
|
||
On macOS, the Dock icon also reopens the window.
|
||
- **Visible network activity.** Pages show a spinner while loading. The top
|
||
bar also shows slow or rate-limited Spotify requests.
|
||
- **One instance.** Launching it again brings the existing window forward
|
||
instead of starting a second copy, on every platform.
|
||
- **Desktop integration.** MPRIS on Linux, so media keys, the shell, and
|
||
`playerctl` see Spotifast like any other player. On macOS and Windows,
|
||
`spotifast next` and its siblings drive the running app from a terminal,
|
||
a launcher, or a hotkey. On Windows, since 0.8.0, hover the taskbar button
|
||
for Previous, Play/Pause, and Next under the window preview. On macOS,
|
||
right-click the Dock icon for Play/Pause, Next, and Previous.
|
||
|
||
## Install
|
||
|
||
On Arch Linux, Spotifast is in the AUR:
|
||
|
||
```bash
|
||
yay -S spotifast-bin # the released build, ready made
|
||
yay -S spotifast # the release, built from source
|
||
yay -S spotifast-git # built from the latest commit
|
||
```
|
||
|
||
Existing AUR installations can switch with the matching command above. Accept
|
||
the offer to replace the old package; saved settings and sign-ins are kept.
|
||
|
||
On macOS, with [Homebrew](https://brew.sh):
|
||
|
||
```sh
|
||
brew install --cask crmne/tap/spotifast
|
||
```
|
||
|
||
Or [download the Mac app](https://spotifast.rocks/download/#macos), open the
|
||
downloaded file, and drag **Spotifast** to **Applications**. Starting with 0.8.0,
|
||
the Mac download passes Apple's security checks. Open it from Applications
|
||
and confirm the normal downloaded-app prompt. No Terminal commands or changes
|
||
to security settings are needed.
|
||
|
||
On Gentoo, [niko-overlays](https://github.com/NikoMalik/niko-overlays) offers
|
||
an optional **community-maintained** package. Its current `0.7.1` ebuild
|
||
builds post-release snapshot `67b8dfb`, rather than the `v0.7.1` release, and
|
||
omits MilkDrop. Use the released binary or build instructions below if you
|
||
want the standard release and feature set.
|
||
|
||
To enable the overlay with `eselect-repository`, run as root:
|
||
|
||
```sh
|
||
emerge --ask app-eselect/eselect-repository
|
||
eselect repository add niko-overlays git https://github.com/NikoMalik/niko-overlays.git
|
||
emaint sync -r niko-overlays
|
||
emerge --ask --autounmask-write media-sound/fastpotify::niko-overlays
|
||
```
|
||
|
||
Review and apply any proposed keyword changes with `dispatch-conf`, then
|
||
repeat the final `emerge` command.
|
||
|
||
Everywhere else, build the single binary with Rust 1.95 or newer:
|
||
|
||
```bash
|
||
cargo install --path . --locked
|
||
```
|
||
|
||
Upgrading a previous Cargo installation requires `--force` once to transfer
|
||
the existing commands to the renamed package.
|
||
|
||
MilkDrop uses libprojectM, which is built from source. This needs CMake, a C++
|
||
compiler, and libclang. To build without MilkDrop or those tools, run
|
||
`cargo install --path . --locked --no-default-features`. On Linux, you also need the
|
||
development packages for ALSA, PulseAudio or PipeWire, and the windowing
|
||
libraries. On Arch:
|
||
|
||
```bash
|
||
sudo pacman -S --needed alsa-lib libpulse libxkbcommon wayland cmake clang
|
||
```
|
||
|
||
and on Debian or Ubuntu:
|
||
|
||
```bash
|
||
sudo apt install libasound2-dev libpulse-dev libxkbcommon-dev libwayland-dev \
|
||
cmake clang libclang-dev
|
||
```
|
||
|
||
and on Fedora:
|
||
|
||
```bash
|
||
sudo dnf install alsa-lib-devel pulseaudio-libs-devel libxkbcommon-devel \
|
||
wayland-devel cmake clang clang-devel
|
||
```
|
||
|
||
On Windows, libprojectM is built with Visual Studio 2022, CMake, LLVM, and
|
||
vcpkg (`vcpkg install glew:x64-windows-static`, with
|
||
`VCPKG_INSTALLATION_ROOT` pointing at the vcpkg folder).
|
||
|
||
With [Nix](https://nixos.org), `nix develop` provides all of it, along with
|
||
the exact toolchain `rust-toolchain.toml` pins.
|
||
|
||
An official public binary cache is not active yet. CI can publish its Linux
|
||
Nix builds once a maintainer configures Cachix; see
|
||
[Nix binary cache setup](docs/_reference/nix-cache.md).
|
||
|
||
On macOS, `packages.<system>.spotifast` contains the native binary and an
|
||
ad-hoc signed `Spotifast.app` bundle for the Dock, Launch Services, and
|
||
`spotify:` links. With nix-darwin, add `spotifast` to
|
||
`environment.systemPackages` and link `"/Applications"` through
|
||
`environment.pathsToLink`; with Home Manager, `home.packages` is enough, as
|
||
its darwin support links the bundle into `~/Applications`.
|
||
|
||
Since 0.8.0, system fallback fonts align with Latin text, including
|
||
Japanese titles drawn with Hiragino Sans on macOS. Yi characters used in
|
||
stylized artist names also use an installed fallback font instead of empty boxes.
|
||
|
||
Spotifast uses system fonts for scripts not covered by its interface font,
|
||
including Chinese, Japanese, Korean, Arabic, Hebrew, Thai, and Indic scripts.
|
||
On macOS it draws each of them with the face the system itself uses, in the
|
||
language order set in System Settings, so Chinese titles follow the
|
||
Traditional or Simplified preference set there. Windows includes common
|
||
fonts. On Linux, install `noto-fonts` and `noto-fonts-cjk` (Arch) or
|
||
`fonts-noto` and `fonts-noto-cjk` (Debian or Ubuntu) if titles appear as
|
||
empty boxes. On `main`, after 0.9.1, Spotifast also looks in every font
|
||
directory named in fontconfig's configuration, so fonts installed through
|
||
NixOS's `fonts.packages` are found too.
|
||
|
||
Since 0.8.0, long right-to-left titles in song rows and the player
|
||
bar end with an ellipsis inside their text area, including joined Arabic letters.
|
||
|
||
On `main`, after 0.9.1, the Linux launcher is
|
||
`packaging/applications/spotifast.desktop`. Its icon and window identity also
|
||
use Spotifast, while existing settings and window positions are preserved.
|
||
After installing it, `xdg-mime default spotifast.desktop x-scheme-handler/spotify`
|
||
chooses Spotifast for `spotify:` links. The published 0.8.0 packages still use
|
||
`fastpotify.desktop`; use that name with `xdg-mime` until updating.
|
||
|
||
## Sign in
|
||
|
||
Press **Sign in with Spotify**. Your browser opens Spotify's consent page
|
||
(Authorization Code with PKCE), so Spotifast never sees your password. The
|
||
app keeps its grants in the system credential store: Secret Service on Linux,
|
||
Keychain on macOS, and Credential Manager on Windows. You usually sign in once
|
||
per machine. If the store is unavailable or locked, a new sign-in works for
|
||
this session and Spotifast explains that it could not save it.
|
||
|
||
Playing music **on this computer** needs a second, one-time browser approval.
|
||
Spotify handles streaming separately from library access. Start it from the
|
||
device menu (**Set up playback here**) or Settings. It needs Spotify
|
||
Premium. Its reusable credential uses the same protected storage, independently
|
||
of the two Web API grants.
|
||
|
||
Since 0.8.0, local playback tries the other available server
|
||
addresses when one cannot connect, including a prompt IPv4/IPv6 fallback.
|
||
Socket and proxy tunnel setup have a five-second limit. See
|
||
[how it connects](docs/_reference/how-it-connects.md#the-engine).
|
||
|
||
On `main`, after 0.9.1, the whole engine connection can take up to 75 seconds,
|
||
including server resolution and authentication. A stalled setup may therefore
|
||
remain **Connecting** longer than one five-second attempt; the outer deadline
|
||
does not guarantee that every fallback will be tried.
|
||
|
||
Existing token files migrate after the protected write has been read back
|
||
successfully. A failed migration keeps the original for recovery and reports
|
||
an error. Sign-out removes shared, personal, and playback grants, including
|
||
legacy files and pending writes. Non-secret revocation markers prevent a
|
||
failed keychain deletion from silently restoring a signed-out session.
|
||
See [credential storage and file locations](docs/_reference/settings-and-files.md).
|
||
Since 0.8.0, Flatpak also preserves its fallback state directory
|
||
across full quits, including on older Flatpak versions.
|
||
New Flatpak builds use the application ID `rocks.spotifast.Spotifast`.
|
||
Existing Flatpak users install the new application and remove the old one;
|
||
see [switching Flatpak installations](docs/_reference/renaming.md#flatpak)
|
||
for retaining settings and history.
|
||
|
||
Playback approval requests Spotify's streaming permission separately. A
|
||
verified personal app can complete sign-in while the shared app is busy.
|
||
|
||
The Web API uses a shared app by default. You can add a personal Spotify
|
||
Development Mode app in Settings → Account for a separate quota. Spotifast
|
||
still uses the shared app for requests that personal apps do not support.
|
||
Since 0.8.0, Premium listeners using shared access see a one-time
|
||
prompt explaining the personal app option, with a button that opens setup.
|
||
Dismissal is remembered across restarts.
|
||
Playlists the shared app would serve are read over the local playback session
|
||
instead when it is signed in. If Spotify stays busy and no personal app is
|
||
configured, Spotifast points you to that setting at most once a day.
|
||
|
||
## Account safety
|
||
|
||
We are not aware of a Spotify account being suspended for using Spotifast
|
||
or another librespot player with Premium. Sign-in happens on Spotify's own
|
||
pages, audio uses the quality included with Premium, DRM stays intact, and
|
||
Spotifast does not rip tracks or block ads.
|
||
|
||
Reported suspensions usually involve modded apps that remove ads from free
|
||
accounts, track ripping, or stream manipulation. Spotifast does none of
|
||
those things, and [CONTRIBUTING.md](CONTRIBUTING.md) prohibits them.
|
||
|
||
## Keyboard shortcuts
|
||
|
||
Since 0.8.0, text fields keep their usual Ctrl, Cmd and Alt arrow
|
||
keys for moving the caret while you type.
|
||
|
||
Hold `Shift` while turning the mouse wheel to scroll horizontal shelves,
|
||
including Made for you and Recently played on Home.
|
||
|
||
The main window exposes named playback controls, library and song rows,
|
||
menus, sliders, and settings switches to screen readers. Use `Tab` and
|
||
`Shift+Tab` to move focus, then `Enter` to activate a control or
|
||
play a focused song. On `main`, after 0.8.0, `Space` always plays or pauses
|
||
the current song unless a text field has focus. In a playlist, album or Liked
|
||
Songs, up and down arrows move focus between whole song rows in the displayed order and scroll them
|
||
into view. Tab still reaches the artist links, Like and More controls.
|
||
On `main`, after 0.9.1, `Ctrl+A` selects every song the list shows,
|
||
`Ctrl+C` copies the selected songs' links one per line, and `Ctrl+V` adds
|
||
the song links on the clipboard to the end of a playlist you can edit.
|
||
A focused text field keeps these keys for its own text.
|
||
Left and right arrows adjust a focused volume or seek
|
||
slider. Windows testing with NVDA and accessibility for Winamp skins are
|
||
still in progress.
|
||
|
||
| Shortcut | What it does |
|
||
| --- | --- |
|
||
| `Space` | Play or pause |
|
||
| `Ctrl+←` / `Ctrl+→` | Previous or next |
|
||
| `Shift+←` / `Shift+→` | Seek 10 seconds |
|
||
| `Ctrl+↑` / `Ctrl+↓` | Volume |
|
||
| `M` | Mute |
|
||
| `B` | Like or unlike the playing song |
|
||
| `S` / `R` | Shuffle / cycle repeat |
|
||
| `Q` | Queue panel |
|
||
| `Ctrl+F` or `/` | Search |
|
||
| `Ctrl+B` | Show or hide the sidebar |
|
||
| `Alt+←` / `Alt+→` | Back or forward |
|
||
| `Ctrl+H` / `Ctrl+L` | Home / Liked Songs |
|
||
| `Ctrl+Shift+A` / `Ctrl+Shift+B` | Playing artist / album |
|
||
| `Ctrl+A` | Select every song in a playlist, album or Liked Songs |
|
||
| `Ctrl+C` / `Ctrl+V` | Copy the selected songs' links / add copied song links to your playlist |
|
||
| `Ctrl+M` | Winamp mini player |
|
||
| `Ctrl+Shift+K` | MilkDrop |
|
||
| `Ctrl+,` | Settings |
|
||
| `Ctrl+/` or `?` | All shortcuts |
|
||
| `Ctrl+Q` | Quit |
|
||
|
||
On macOS, `Cmd` replaces `Ctrl`.
|
||
|
||
On Windows, since 0.8.0, middle-click a scrolling list and move the pointer to
|
||
autoscroll. Click, press Esc, use the wheel or switch windows to stop.
|
||
It works automatically on Windows. On Linux, turn on **Middle-click
|
||
autoscroll** under **Settings > Appearance**; it is off by default because a
|
||
middle click usually pastes there. See [autoscroll](docs/_guide/using-spotifast.md#middle-click-autoscroll).
|
||
|
||
## Controlling it from outside
|
||
|
||
On Linux, Spotifast is an MPRIS player, so `playerctl --player=spotifast
|
||
play-pause` already works. `spotifast like` adds or removes the playing
|
||
track from your library.
|
||
|
||
macOS and Windows have no such bus, so the same verbs are subcommands. They
|
||
talk to the instance already running and print nothing on success:
|
||
|
||
```
|
||
spotifast play-pause spotifast volume 40
|
||
spotifast play spotifast volume-up [percent]
|
||
spotifast pause spotifast volume-down [percent]
|
||
spotifast next spotifast mute
|
||
spotifast previous spotifast shuffle [on|off]
|
||
spotifast seek 15 spotifast repeat [off|context|track]
|
||
spotifast seek -- -15 spotifast like
|
||
spotifast seek-to 90 spotifast play-uri spotify:playlist:37i9…
|
||
spotifast show spotifast transfer <device-id>
|
||
spotifast now-playing [--raw] spotifast devices [--raw]
|
||
```
|
||
|
||
`shuffle` and `repeat` toggle when used without an argument. Pass a state to
|
||
set it directly. `like` adds or removes the playing track from your library.
|
||
|
||
`now-playing` prints one readable line. `--raw` prints tab-separated fields:
|
||
state, title, artists, album, position_ms, duration_ms, volume, shuffle,
|
||
repeat, art_url, saved, and device. `saved` is `yes`, `no`, or `unknown` while
|
||
loading. New fields are appended to keep older scripts working.
|
||
|
||
`devices` lists Spotify Connect devices with the ID first and the active one
|
||
marked with `*`. `--raw` prints JSON. The command refreshes the device list,
|
||
so the first call after startup may be empty. Run it again if needed.
|
||
|
||
A verb exits non-zero when Spotifast is not running.
|
||
|
||
On every platform, `spotifast <link>` opens a Spotify link, a `spotify:`
|
||
URI or an `open.spotify.com` address, in the running app, or starts the
|
||
app on it. This is what the desktop runs when a link is clicked.
|
||
|
||
On `main`, after 0.8.0, search links open Search with the query filled in,
|
||
without starting playback. They work on a fresh launch or an existing window;
|
||
if signed out, the search waits for sign-in. For example:
|
||
|
||
```sh
|
||
spotifast 'https://open.spotify.com/search/here%20comes%20the%20sun'
|
||
# Linux, with Spotifast already running:
|
||
playerctl --player=spotifast open 'https://open.spotify.com/search/here%20comes%20the%20sun'
|
||
```
|
||
|
||
Use `spotify:search:here%20comes%20the%20sun` for the equivalent Spotify URI,
|
||
or `https://open.spotify.com/search` to open an empty search box. Encode spaces
|
||
as `%20`; a `+` in the path remains a literal plus. Ordinary MPRIS playback
|
||
URIs still start playback.
|
||
|
||
Launchers such as Raycast or Alfred can use these commands. The Stream Deck
|
||
plugin uses the same interface.
|
||
|
||
## Settings
|
||
|
||
Settings live in one readable JSON file (`~/.config/spotifast/settings.json`
|
||
on Linux). They include the Connect device name, bitrate, normalisation,
|
||
autoplay, gapless playback, the audio backend (PulseAudio/PipeWire or ALSA on
|
||
Linux), audio cache size, theme, sidebar state, whether pages take colour
|
||
from artwork, and the mini player's skin and size.
|
||
Since 0.8.0, you can hide Made for you and Recommended for you
|
||
from Home through JSON preferences; see
|
||
[Home shelves](docs/_reference/settings-and-files.md#home-shelves).
|
||
Custom JSON palettes go in a `themes` folder beside `settings.json`.
|
||
Select them in Appearance; `spotifast reload-themes` loads additions and updates
|
||
without interrupting playback. See [custom themes and Omarchy integration](docs/_reference/settings-and-files.md#custom-themes).
|
||
New installations default to **Follow system**. Linux packages include Omarchy
|
||
integration, set up its per-user template and hook automatically on first launch,
|
||
and follow the current palette. Existing theme choices and custom files stay
|
||
intact. The picker lists Follow system, Light and Dark first, then the available Omarchy
|
||
integration and local palettes. The **Open themes folder** button in Settings
|
||
opens the local JSON palette directory.
|
||
The interface follows the operating system's language when Spotifast has a
|
||
translation for it, and English otherwise. **Settings → Appearance → Language**
|
||
picks another one, listed by its own name, and applies it at once; **System**
|
||
follows the computer again. Anything a translation does not cover yet appears
|
||
in English.
|
||
Playback settings apply when you press **Apply and restart playback**.
|
||
The Settings page has its own search: type under the title to narrow the
|
||
rows, clear the field to see everything again.
|
||
You can also check for a new release from Settings. On macOS, the same command
|
||
is in the application menu.
|
||
|
||
The Windows installer, Mac app, and portable Windows and Linux downloads
|
||
support updates from inside Spotifast. Click the green update button to
|
||
download a release, then choose when to restart and install it. Settings can
|
||
enable automatic background downloads; restarting always waits for your click.
|
||
Closing the update window keeps a download running.
|
||
|
||
Spotifast checks each download before installing it. An interrupted or damaged
|
||
download leaves the running app alone, and a failed startup restores the
|
||
previous installation. Updates keep your settings and sign-ins. On macOS,
|
||
move Spotifast to Applications before updating it. See
|
||
[how updates are checked and installed](docs/_reference/how-it-connects.md#what-the-client-stores)
|
||
for the technical details.
|
||
|
||
Package-managed installations continue to update through their package manager,
|
||
including Homebrew, Flatpak, apt, dnf, pacman, Nix, and Cargo. Unrecognized
|
||
installations use the download page. Portable archives identify themselves with
|
||
`spotifast-portable.txt`; older archives need one manual upgrade to an
|
||
update-enabled build.
|
||
|
||
On `main`, after 0.8.0, Off and System proxies apply immediately. HTTP and SOCKS5 apply
|
||
when you press **Apply settings**, and can also be set on the sign-in screen.
|
||
A proxy password uses the system credential store, separately from Spotify
|
||
sign-in. Only confirmed proxy settings are saved; editing a form does not
|
||
change the active connection until you apply it.
|
||
Proxy authentication covers Web requests. Local playback can use only an
|
||
unauthenticated HTTP proxy; with proxy login or SOCKS5 it connects directly.
|
||
|
||
Caches (audio, artwork) live under the cache directory and can be deleted at
|
||
any time without signing you out.
|
||
On `main`, after 0.8.0, downloaded artwork uses less temporary memory while
|
||
being saved to the cache. Visible cards and collection covers use sharper
|
||
640-pixel artwork. Loading transitions may retain up to 64 softened previews
|
||
in addition to the existing artwork-cache budget. These previews reuse decoded
|
||
artwork, so keeping a collection open does not repeatedly reload its cover.
|
||
|
||
For blank or incorrectly drawn windows, include `spotifast.log` in the bug
|
||
report. On `main`, after 0.8.0, it records the app version, platform and active
|
||
OpenGL renderer, plus window-creation errors even when launched without a console.
|
||
|
||
## How it is built
|
||
|
||
- `src/player.rs`: librespot playback, mixing, and Spotify Connect state.
|
||
- `src/api/`: shared and personal Web API sessions, routing, concurrency, and
|
||
rate limits.
|
||
- `src/backend.rs`: the tokio runtime and channels used by the interface.
|
||
- `src/images.rs`: album art loading, caching, and accent-colour extraction.
|
||
- `src/app.rs`, `src/model.rs`, `src/ui/`: state, navigation, and views.
|
||
- `src/mpris.rs`: Linux media controls.
|
||
|
||
Spotifast pins its Rust toolchain in `rust-toolchain.toml`; `cargo test`
|
||
covers the API models, dual-session routing, PKCE, the player state machine,
|
||
and a headless render of every page, panel, and dialog.
|
||
|
||
To look at the interface without a Spotify account, build with the `demo`
|
||
feature and start it with sample data:
|
||
|
||
```bash
|
||
cargo run --features demo -- --demo --demo-page playlist:pl1 --demo-show queue
|
||
```
|
||
|
||
Demo mode never writes settings. `--demo-shot <PATH>` writes the window to a
|
||
PNG and exits, which is useful for reproducible interface screenshots.
|
||
`--demo-size WIDTHxHEIGHT` sets the window size in logical pixels for that shot.
|
||
`--demo-drag X,Y:X,Y` holds a drag in the shot: it presses at the first point
|
||
and keeps the button down at the second.
|
||
Demo windows ignore saved window geometry and do not save window or interface state.
|
||
Use `--demo-data <DIRECTORY>` to keep demo caches and logs in a separate directory.
|
||
|
||
## Contributing
|
||
|
||
Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening an issue or pull
|
||
request. It covers project scope and required checks.
|
||
|
||
Translations use standard gettext `.po` files in `assets/i18n/`, with an English
|
||
`.pot` template. The interface is marked for translation throughout and ships
|
||
with 13 translations, including Portuguese and Chinese variants.
|
||
Spanish is complete; the others cover the earlier navigation, player and panel
|
||
labels and fall back to English for the rest. See
|
||
[Translating Spotifast](docs/_reference/translating.md) for editing with existing
|
||
translation tools, previewing, and reporting translation problems.
|
||
|
||
New and reopened issues and new discussions receive automated triage through
|
||
[Copilot Triage](https://github.com/crmne/copilot-triage). A party-popper reaction
|
||
marks a completed assessment; it does not promise a reply or a fix. See
|
||
[automated triage](CONTRIBUTING.md#automated-triage) for details.
|
||
|
||
## Acknowledgements
|
||
|
||
Spotifast uses [librespot](https://github.com/librespot-org/librespot),
|
||
[egui](https://github.com/emilk/egui), the [Inter](https://rsms.me/inter/)
|
||
typeface (OFL), and [Lucide](https://lucide.dev) icons (ISC).
|
||
|
||
Spotifast is an independent project and is not affiliated with Spotify.
|
||
Spotify is a trademark of Spotify AB.
|
||
|
||
Licensed under the [MIT License](LICENSE).
|
||
|
||
## Packaging maintenance
|
||
|
||
Release packaging uses the [native-packages](https://rubygems.org/gems/native-packages) gem. macOS release builds automatically sign and notarize when the Apple CI credentials are configured. `native-packages.yaml` declares packages and downstream repositories; native recipes and installation assets live in `packaging/`; see [PACKAGING.md](PACKAGING.md) for local commands and CI behavior.
|