documentation
This commit is contained in:
+258
@@ -0,0 +1,258 @@
|
||||
# API Reference
|
||||
|
||||
Shanty exposes a REST API at `/api/*` and a Subsonic-compatible API at `/rest/*`. All REST endpoints require authentication via session cookie unless noted otherwise.
|
||||
|
||||
## Authentication
|
||||
|
||||
All `/api/*` endpoints (except the auth endpoints listed below) require an active session. To authenticate, call the login endpoint and include the returned session cookie in subsequent requests.
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/auth/setup-required` | No | Check if initial setup is needed (returns `{"required": true}` if no users exist) |
|
||||
| POST | `/api/auth/setup` | No | Create the first admin user. Only works when no users exist. Body: `{"username": "...", "password": "..."}` |
|
||||
| POST | `/api/auth/login` | No | Log in. Body: `{"username": "...", "password": "..."}`. Returns user info and sets session cookie. |
|
||||
| POST | `/api/auth/logout` | Yes | Log out and clear session. |
|
||||
| GET | `/api/auth/me` | Yes | Get current user info (id, username, role). |
|
||||
| GET | `/api/auth/users` | Admin | List all users. |
|
||||
| POST | `/api/auth/users` | Admin | Create a new user. Body: `{"username": "...", "password": "..."}` |
|
||||
| DELETE | `/api/auth/users/{id}` | Admin | Delete a user. Cannot delete yourself. |
|
||||
| PUT | `/api/auth/subsonic-password` | Yes | Set Subsonic password for current user. Body: `{"password": "..."}` |
|
||||
| GET | `/api/auth/subsonic-password-status` | Yes | Check if current user has a Subsonic password set. |
|
||||
|
||||
---
|
||||
|
||||
## Artists
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/artists` | Yes | List all artists in the library. Supports `?limit=50&offset=0` pagination. Returns artist names, MBIDs, monitored status, and track counts (watched/owned/total). |
|
||||
| POST | `/api/artists` | Yes | Add (watch) an artist. Body: `{"name": "...", "mbid": "..."}`. At least one of name or mbid is required. Expands the artist's full discography into individual track wanted_items. |
|
||||
| GET | `/api/artists/{id}` | Yes | Get artist by local database ID. Returns artist info and local albums. |
|
||||
| GET | `/api/artists/{id}/full` | Yes | Get full artist detail with MusicBrainz enrichment. Accepts local ID or MBID. Returns discography with per-album status (owned/partial/wanted/unwatched), artist photo, bio, and banner. Supports `?quick=true` to skip per-album track fetches. |
|
||||
| DELETE | `/api/artists/{id}` | Admin | Delete an artist from the library. |
|
||||
| POST | `/api/artists/{id}/monitor` | Yes | Enable monitoring for an artist. |
|
||||
| DELETE | `/api/artists/{id}/monitor` | Yes | Disable monitoring for an artist. |
|
||||
|
||||
---
|
||||
|
||||
## Albums
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/albums` | Yes | List all local albums. Supports `?limit=50&offset=0`. |
|
||||
| POST | `/api/albums` | Yes | Add (watch) an album. Body: `{"artist": "...", "album": "...", "mbid": "..."}`. Accepts release or release-group MBID. Expands to individual track wanted_items. |
|
||||
| GET | `/api/albums/{mbid}` | Yes | Get album track listing by MBID (release or release-group). Returns tracks with per-track status. |
|
||||
|
||||
---
|
||||
|
||||
## Tracks
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/tracks` | Yes | List tracks. Supports `?limit=50&offset=0` and `?q=search` for text search. |
|
||||
| GET | `/api/tracks/{id}` | Yes | Get a single track by local database ID. |
|
||||
|
||||
---
|
||||
|
||||
## Search
|
||||
|
||||
Search queries MusicBrainz (either the local database or the remote API).
|
||||
|
||||
| Method | Path | Auth | Parameters | Description |
|
||||
|--------|------|------|------------|-------------|
|
||||
| GET | `/api/search/artist` | Yes | `q` (required), `limit` (default 25) | Search for artists by name. Returns MBID, name, disambiguation. |
|
||||
| GET | `/api/search/album` | Yes | `q` (required), `artist` (optional), `limit` (default 25) | Search for albums. |
|
||||
| GET | `/api/search/track` | Yes | `q` (required), `artist` (optional), `limit` (default 25) | Search for tracks. |
|
||||
| GET | `/api/search/discography/{mbid}` | Yes | (none) | Get an artist's full discography (release groups) by MBID. |
|
||||
|
||||
---
|
||||
|
||||
## Downloads
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/downloads/queue` | Yes | List download queue. Optional `?status=pending\|downloading\|completed\|failed\|cancelled`. |
|
||||
| POST | `/api/downloads` | Yes | Enqueue a manual download. Body: `{"query": "..."}`. |
|
||||
| POST | `/api/downloads/sync` | Yes | Sync wanted items to download queue. Returns count of found/enqueued/skipped. |
|
||||
| POST | `/api/downloads/process` | Yes | Start processing the download queue (background task). Returns a task_id. |
|
||||
| POST | `/api/downloads/retry/{id}` | Yes | Requeue a failed download. |
|
||||
| DELETE | `/api/downloads/{id}` | Yes | Cancel a download. |
|
||||
|
||||
---
|
||||
|
||||
## Playlists
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| POST | `/api/playlists/generate` | Yes | Generate a playlist (preview, not saved). Body includes strategy, seed_artists, count, etc. |
|
||||
| GET | `/api/playlists` | Yes | List saved playlists for the current user. |
|
||||
| POST | `/api/playlists` | Yes | Save a playlist. Body: `{"name": "...", "description": "...", "track_ids": [1, 2, 3]}` |
|
||||
| GET | `/api/playlists/{id}` | Yes | Get a playlist with its tracks. |
|
||||
| PUT | `/api/playlists/{id}` | Yes | Update playlist name/description. Body: `{"name": "...", "description": "..."}` |
|
||||
| DELETE | `/api/playlists/{id}` | Yes | Delete a playlist. |
|
||||
| GET | `/api/playlists/{id}/m3u` | Yes | Export playlist as M3U file download. |
|
||||
| POST | `/api/playlists/{id}/tracks` | Yes | Add a track. Body: `{"track_id": 123}` |
|
||||
| PUT | `/api/playlists/{id}/tracks` | Yes | Reorder tracks. Body: `{"track_ids": [3, 1, 2]}` |
|
||||
| DELETE | `/api/playlists/{id}/tracks/{track_id}` | Yes | Remove a track from the playlist. |
|
||||
|
||||
### Playlist Generation Body
|
||||
|
||||
```json
|
||||
{
|
||||
"strategy": "similar",
|
||||
"seed_artists": ["Pink Floyd", "Radiohead"],
|
||||
"count": 50,
|
||||
"popularity_bias": 0.5,
|
||||
"ordering": "interleave",
|
||||
"genres": [],
|
||||
"rules": []
|
||||
}
|
||||
```
|
||||
|
||||
Strategies: `similar`, `genre`, `random`, `smart`.
|
||||
Ordering options: `interleave`, `score`, `random`.
|
||||
|
||||
---
|
||||
|
||||
## Lyrics
|
||||
|
||||
| Method | Path | Auth | Parameters | Description |
|
||||
|--------|------|------|------------|-------------|
|
||||
| GET | `/api/lyrics` | Yes | `artist` (required), `title` (required) | Fetch lyrics from LRCLIB. Returns plain lyrics and time-synced lyrics if available. Cached for 30 days. |
|
||||
|
||||
---
|
||||
|
||||
## System and Pipeline
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/status` | Yes | Dashboard status: library summary, download queue, tagging queue, active tasks, scheduler info. |
|
||||
| POST | `/api/pipeline` | Yes | Trigger the full pipeline (sync + download + tag + organize). Returns task_ids. |
|
||||
| POST | `/api/index` | Yes | Trigger a library scan (background task). |
|
||||
| POST | `/api/tag` | Yes | Trigger tagging of untagged tracks (background task). |
|
||||
| POST | `/api/organize` | Yes | Trigger file organization (background task). |
|
||||
| GET | `/api/tasks/{id}` | Yes | Get task status (running/completed/failed, progress, message). |
|
||||
|
||||
---
|
||||
|
||||
## Watchlist
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/watchlist` | Yes | List wanted items for the current user. |
|
||||
| DELETE | `/api/watchlist/{id}` | Yes | Remove a wanted item. |
|
||||
|
||||
---
|
||||
|
||||
## YouTube Authentication
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/ytauth/status` | Yes | Get YouTube auth status: authenticated, cookie age, refresh status, yt-dlp version, API key status. |
|
||||
| POST | `/api/ytauth/login-start` | Admin | Launch Firefox + noVNC for interactive YouTube login. Returns VNC URL. |
|
||||
| POST | `/api/ytauth/login-stop` | Admin | Stop Firefox, export cookies, enable auto-refresh. |
|
||||
| POST | `/api/ytauth/refresh` | Admin | Trigger immediate headless cookie refresh. |
|
||||
| DELETE | `/api/ytauth/cookies` | Admin | Clear all cookies and Firefox profile, disable refresh. |
|
||||
|
||||
---
|
||||
|
||||
## Monitor
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| POST | `/api/monitor/check` | Admin | Trigger an immediate check of all monitored artists for new releases. |
|
||||
| GET | `/api/monitor/status` | Yes | List all monitored artists with last check timestamps. |
|
||||
|
||||
---
|
||||
|
||||
## Scheduler
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| POST | `/api/scheduler/skip-pipeline` | Admin | Skip the next scheduled pipeline run. |
|
||||
| POST | `/api/scheduler/skip-monitor` | Admin | Skip the next scheduled monitor check. |
|
||||
|
||||
---
|
||||
|
||||
## MusicBrainz
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/mb-status` | Yes | Check if local MusicBrainz database is available and get stats (artist/release/recording counts). |
|
||||
| POST | `/api/mb-import` | Admin | Trigger MusicBrainz database import (background task). Downloads dumps and imports. |
|
||||
|
||||
---
|
||||
|
||||
## Config
|
||||
|
||||
| Method | Path | Auth | Description |
|
||||
|--------|------|------|-------------|
|
||||
| GET | `/api/config` | Yes | Get current configuration. |
|
||||
| PUT | `/api/config` | Admin | Update configuration. Body is the full AppConfig JSON object. Writes to YAML file and updates in-memory config. |
|
||||
|
||||
---
|
||||
|
||||
## Subsonic API
|
||||
|
||||
The Subsonic API is served at `/rest/*` and uses the Subsonic authentication protocol (username + MD5 token or plaintext password, passed as query parameters).
|
||||
|
||||
All Subsonic endpoints accept the standard Subsonic query parameters: `u` (username), `p` (password or `enc:` hex-encoded), `t` (MD5 token), `s` (salt), `v` (API version), `c` (client name), `f` (response format, defaults to XML).
|
||||
|
||||
Each endpoint is available at both `/rest/endpoint` and `/rest/endpoint.view`.
|
||||
|
||||
### System
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `/rest/ping` | Server health check. |
|
||||
| `/rest/getLicense` | Returns license status (always valid). |
|
||||
|
||||
### Browsing
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `/rest/getMusicFolders` | List music library folders. |
|
||||
| `/rest/getIndexes` | Get alphabetical artist index. |
|
||||
| `/rest/getMusicDirectory` | Get contents of a directory (artist's albums or album's tracks). Parameter: `id`. |
|
||||
| `/rest/getArtists` | Get all artists (ID3 tag based). |
|
||||
| `/rest/getArtist` | Get an artist with albums. Parameter: `id`. |
|
||||
| `/rest/getAlbum` | Get an album with tracks. Parameter: `id`. |
|
||||
| `/rest/getSong` | Get a single track. Parameter: `id`. |
|
||||
| `/rest/getGenres` | List all genres. |
|
||||
|
||||
### Search
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `/rest/search3` | Search artists, albums, and tracks. Parameters: `query`, `artistCount`, `albumCount`, `songCount`, `artistOffset`, `albumOffset`, `songOffset`. |
|
||||
|
||||
### Media
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `/rest/stream` | Stream an audio file. Parameter: `id`. Transcodes Opus to MP3 if transcoding is enabled. |
|
||||
| `/rest/download` | Download an audio file (original format). Parameter: `id`. |
|
||||
| `/rest/getCoverArt` | Get cover art image. Parameter: `id`. |
|
||||
|
||||
### Playlists
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `/rest/getPlaylists` | List all playlists. |
|
||||
| `/rest/getPlaylist` | Get a playlist with tracks. Parameter: `id`. |
|
||||
| `/rest/createPlaylist` | Create or update a playlist. Parameters: `name`, `songId` (repeatable). |
|
||||
| `/rest/deletePlaylist` | Delete a playlist. Parameter: `id`. |
|
||||
|
||||
### Annotation
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `/rest/scrobble` | Record a play. Parameters: `id`, `submission` (true/false). |
|
||||
|
||||
### User
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `/rest/getUser` | Get user details. Parameter: `username`. |
|
||||
@@ -0,0 +1,461 @@
|
||||
# Configuration Reference
|
||||
|
||||
Shanty is configured via a YAML file and environment variables. Environment variables always override values from the YAML file.
|
||||
|
||||
## Config File Location
|
||||
|
||||
By default, Shanty looks for its config file at:
|
||||
|
||||
- **Linux:** `~/.config/shanty/config.yaml`
|
||||
- **Docker:** `/config/config.yaml`
|
||||
- **Custom:** Set the `SHANTY_CONFIG` environment variable to any path.
|
||||
|
||||
If no config file exists, Shanty uses sensible defaults for everything. You can also configure most settings from the web UI under **Settings**, which writes changes back to the YAML file.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
These environment variables override their corresponding YAML settings. In Docker, set them in the `environment` section of your `docker-compose.yml`.
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `SHANTY_CONFIG` | `~/.config/shanty/config.yaml` | Path to the YAML config file |
|
||||
| `SHANTY_DATA_DIR` | `~/.local/share/shanty` | Base directory for application data (database, downloads, Firefox profile). In Docker, this is `/data`. |
|
||||
| `SHANTY_DATABASE_URL` | `sqlite://~/.local/share/shanty/shanty.db?mode=rwc` | Full SQLite connection string |
|
||||
| `SHANTY_LIBRARY_PATH` | System music directory (`~/Music`) | Path to your music library |
|
||||
| `SHANTY_WEB_PORT` | `8085` | HTTP server port |
|
||||
| `SHANTY_WEB_BIND` | `0.0.0.0` | HTTP server bind address |
|
||||
| `SHANTY_LASTFM_API_KEY` | (none) | Last.fm API key for artist bios and similar-artist playlists. Get one at https://www.last.fm/api/account/create |
|
||||
| `SHANTY_FANART_API_KEY` | (none) | fanart.tv API key for artist images and banners. Get one at https://fanart.tv/get-an-api-key/ |
|
||||
|
||||
## Full Config Reference
|
||||
|
||||
Below is every configuration option grouped by section.
|
||||
|
||||
---
|
||||
|
||||
### Root Options
|
||||
|
||||
These are top-level keys in the YAML file.
|
||||
|
||||
#### `library_path`
|
||||
- **Type:** string (file path)
|
||||
- **Default:** System music directory (e.g., `~/Music`)
|
||||
- **Env override:** `SHANTY_LIBRARY_PATH`
|
||||
- **Description:** The root directory of your music library. Organized files are placed here according to the `organization_format` template.
|
||||
- **Example:** `library_path: /home/user/Music`
|
||||
|
||||
#### `database_url`
|
||||
- **Type:** string
|
||||
- **Default:** `sqlite://~/.local/share/shanty/shanty.db?mode=rwc`
|
||||
- **Env override:** `SHANTY_DATABASE_URL`
|
||||
- **Description:** SQLite database connection string. The `?mode=rwc` suffix means read-write-create (the database file is created automatically if it does not exist).
|
||||
- **Example:** `database_url: sqlite:///data/shanty.db?mode=rwc`
|
||||
|
||||
#### `download_path`
|
||||
- **Type:** string (file path)
|
||||
- **Default:** `~/.local/share/shanty/downloads`
|
||||
- **Description:** Temporary directory where yt-dlp stores downloaded files before they are tagged and organized into the library.
|
||||
- **Example:** `download_path: /tmp/shanty-downloads`
|
||||
|
||||
#### `organization_format`
|
||||
- **Type:** string (template)
|
||||
- **Default:** `{artist}/{album}/{track_number} - {title}.{ext}`
|
||||
- **Description:** Template for organizing files in the library. Available placeholders: `{artist}`, `{album}`, `{title}`, `{track_number}`, `{ext}`, `{year}`, `{genre}`.
|
||||
- **Example:** `organization_format: "{artist}/{album} ({year})/{track_number} - {title}.{ext}"`
|
||||
|
||||
#### `allowed_secondary_types`
|
||||
- **Type:** list of strings
|
||||
- **Default:** `[]` (empty, meaning studio albums only)
|
||||
- **Description:** Which secondary release group types to include when displaying an artist's discography. By default, only pure studio albums (with no secondary type) are shown. Add types to this list to also see compilations, live albums, etc.
|
||||
- **Options:** `Compilation`, `Live`, `Soundtrack`, `Remix`, `DJ-mix`, `Demo`
|
||||
- **Example:**
|
||||
```yaml
|
||||
allowed_secondary_types:
|
||||
- Compilation
|
||||
- Live
|
||||
```
|
||||
|
||||
#### `log_level`
|
||||
- **Type:** string
|
||||
- **Default:** `info`
|
||||
- **Description:** Log verbosity level. The `-v` CLI flag overrides this at runtime.
|
||||
- **Options:** `error`, `warn`, `info`, `debug`, `trace`
|
||||
- **Example:** `log_level: debug`
|
||||
|
||||
---
|
||||
|
||||
### `web` Section
|
||||
|
||||
Controls the HTTP server.
|
||||
|
||||
#### `web.port`
|
||||
- **Type:** integer
|
||||
- **Default:** `8085`
|
||||
- **Env override:** `SHANTY_WEB_PORT`
|
||||
- **Description:** Port the web server listens on.
|
||||
- **Example:**
|
||||
```yaml
|
||||
web:
|
||||
port: 9090
|
||||
```
|
||||
|
||||
#### `web.bind`
|
||||
- **Type:** string
|
||||
- **Default:** `0.0.0.0`
|
||||
- **Env override:** `SHANTY_WEB_BIND`
|
||||
- **Description:** Address the web server binds to. Use `0.0.0.0` to accept connections from any interface, or `127.0.0.1` to restrict to localhost.
|
||||
- **Example:**
|
||||
```yaml
|
||||
web:
|
||||
bind: 127.0.0.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `tagging` Section
|
||||
|
||||
Controls automatic file tagging behavior.
|
||||
|
||||
#### `tagging.auto_tag`
|
||||
- **Type:** boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** Whether to automatically tag files during indexing. When false, tagging must be triggered manually or as part of the pipeline.
|
||||
- **Example:**
|
||||
```yaml
|
||||
tagging:
|
||||
auto_tag: true
|
||||
```
|
||||
|
||||
#### `tagging.write_tags`
|
||||
- **Type:** boolean
|
||||
- **Default:** `true`
|
||||
- **Description:** Whether to actually write tags to audio files. When false, the tagger runs in dry-run mode (useful for testing).
|
||||
- **Example:**
|
||||
```yaml
|
||||
tagging:
|
||||
write_tags: false
|
||||
```
|
||||
|
||||
#### `tagging.confidence`
|
||||
- **Type:** float (0.0 to 1.0)
|
||||
- **Default:** `0.8`
|
||||
- **Description:** Minimum confidence threshold for fuzzy matching when the tagger tries to identify a track. Higher values mean stricter matching. Tracks below this threshold are skipped.
|
||||
- **Example:**
|
||||
```yaml
|
||||
tagging:
|
||||
confidence: 0.9
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `download` Section
|
||||
|
||||
Controls the download backend (yt-dlp).
|
||||
|
||||
#### `download.format`
|
||||
- **Type:** string
|
||||
- **Default:** `opus`
|
||||
- **Description:** Audio format for downloaded files.
|
||||
- **Options:** `opus`, `mp3`, `m4a`, `flac`
|
||||
- **Example:**
|
||||
```yaml
|
||||
download:
|
||||
format: mp3
|
||||
```
|
||||
|
||||
#### `download.search_source`
|
||||
- **Type:** string
|
||||
- **Default:** `ytmusic`
|
||||
- **Description:** Search backend for finding tracks to download.
|
||||
- **Options:** `ytmusic` (YouTube Music via ytmusicapi)
|
||||
- **Example:**
|
||||
```yaml
|
||||
download:
|
||||
search_source: ytmusic
|
||||
```
|
||||
|
||||
#### `download.cookies_path`
|
||||
- **Type:** string (file path) or null
|
||||
- **Default:** null (no cookies)
|
||||
- **Description:** Path to a Netscape-format cookies file for YouTube authentication. Usually managed automatically by the YouTube auth feature. When set, the authenticated rate limit is used.
|
||||
- **Example:**
|
||||
```yaml
|
||||
download:
|
||||
cookies_path: /data/cookies.txt
|
||||
```
|
||||
|
||||
#### `download.rate_limit`
|
||||
- **Type:** integer
|
||||
- **Default:** `250`
|
||||
- **Description:** Maximum download requests per hour when not authenticated. YouTube's actual limit is roughly 300; the default includes a safety margin.
|
||||
- **Example:**
|
||||
```yaml
|
||||
download:
|
||||
rate_limit: 200
|
||||
```
|
||||
|
||||
#### `download.rate_limit_auth`
|
||||
- **Type:** integer
|
||||
- **Default:** `1800`
|
||||
- **Description:** Maximum download requests per hour when authenticated with cookies. YouTube's actual limit is roughly 2000; the default includes a safety margin.
|
||||
- **Example:**
|
||||
```yaml
|
||||
download:
|
||||
rate_limit_auth: 1500
|
||||
```
|
||||
|
||||
#### `download.cookie_refresh_enabled`
|
||||
- **Type:** boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** Whether to automatically refresh YouTube cookies using headless Firefox. Enabled automatically when you log in via the YouTube Authentication feature in Settings.
|
||||
- **Example:**
|
||||
```yaml
|
||||
download:
|
||||
cookie_refresh_enabled: true
|
||||
```
|
||||
|
||||
#### `download.cookie_refresh_hours`
|
||||
- **Type:** integer
|
||||
- **Default:** `6`
|
||||
- **Description:** How often (in hours) to refresh YouTube cookies. YouTube cookies typically expire after about 2 weeks, so refreshing every 6 hours keeps them fresh.
|
||||
- **Example:**
|
||||
```yaml
|
||||
download:
|
||||
cookie_refresh_hours: 12
|
||||
```
|
||||
|
||||
#### `download.vnc_port`
|
||||
- **Type:** integer
|
||||
- **Default:** `6080`
|
||||
- **Description:** Port for the noVNC web interface used during interactive YouTube login. This port must be accessible from your browser.
|
||||
- **Example:**
|
||||
```yaml
|
||||
download:
|
||||
vnc_port: 6081
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `indexing` Section
|
||||
|
||||
Controls the library scanner.
|
||||
|
||||
#### `indexing.concurrency`
|
||||
- **Type:** integer
|
||||
- **Default:** `4`
|
||||
- **Description:** Number of files to process concurrently during a library scan. Higher values use more CPU and memory but scan faster.
|
||||
- **Example:**
|
||||
```yaml
|
||||
indexing:
|
||||
concurrency: 8
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `metadata` Section
|
||||
|
||||
Controls where artist metadata, images, lyrics, and cover art come from.
|
||||
|
||||
#### `metadata.metadata_source`
|
||||
- **Type:** string
|
||||
- **Default:** `musicbrainz`
|
||||
- **Description:** Source for structured metadata (artist info, release data, track listings).
|
||||
- **Options:** `musicbrainz`
|
||||
- **Example:**
|
||||
```yaml
|
||||
metadata:
|
||||
metadata_source: musicbrainz
|
||||
```
|
||||
|
||||
#### `metadata.artist_image_source`
|
||||
- **Type:** string
|
||||
- **Default:** `wikipedia`
|
||||
- **Description:** Source for artist photos. Wikipedia works without an API key. fanart.tv provides higher quality images and background banners but requires `SHANTY_FANART_API_KEY`.
|
||||
- **Options:** `wikipedia`, `fanarttv`
|
||||
- **Example:**
|
||||
```yaml
|
||||
metadata:
|
||||
artist_image_source: fanarttv
|
||||
```
|
||||
|
||||
#### `metadata.artist_bio_source`
|
||||
- **Type:** string
|
||||
- **Default:** `wikipedia`
|
||||
- **Description:** Source for artist biographies. Wikipedia works without an API key. Last.fm provides more music-focused bios but requires `SHANTY_LASTFM_API_KEY`.
|
||||
- **Options:** `wikipedia`, `lastfm`
|
||||
- **Example:**
|
||||
```yaml
|
||||
metadata:
|
||||
artist_bio_source: lastfm
|
||||
```
|
||||
|
||||
#### `metadata.lyrics_source`
|
||||
- **Type:** string
|
||||
- **Default:** `lrclib`
|
||||
- **Description:** Source for song lyrics. LRCLIB provides both plain and time-synced lyrics.
|
||||
- **Options:** `lrclib`
|
||||
- **Example:**
|
||||
```yaml
|
||||
metadata:
|
||||
lyrics_source: lrclib
|
||||
```
|
||||
|
||||
#### `metadata.cover_art_source`
|
||||
- **Type:** string
|
||||
- **Default:** `coverartarchive`
|
||||
- **Description:** Source for album cover art.
|
||||
- **Options:** `coverartarchive`
|
||||
- **Example:**
|
||||
```yaml
|
||||
metadata:
|
||||
cover_art_source: coverartarchive
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `scheduling` Section
|
||||
|
||||
Controls automatic background tasks.
|
||||
|
||||
#### `scheduling.pipeline_enabled`
|
||||
- **Type:** boolean
|
||||
- **Default:** `true`
|
||||
- **Description:** Whether the download pipeline (sync, download, tag, organize) runs automatically on a schedule.
|
||||
- **Example:**
|
||||
```yaml
|
||||
scheduling:
|
||||
pipeline_enabled: false
|
||||
```
|
||||
|
||||
#### `scheduling.pipeline_interval_hours`
|
||||
- **Type:** integer
|
||||
- **Default:** `3`
|
||||
- **Description:** Hours between automatic pipeline runs. The timer starts after the previous run completes.
|
||||
- **Example:**
|
||||
```yaml
|
||||
scheduling:
|
||||
pipeline_interval_hours: 6
|
||||
```
|
||||
|
||||
#### `scheduling.monitor_enabled`
|
||||
- **Type:** boolean
|
||||
- **Default:** `true`
|
||||
- **Description:** Whether the monitor automatically checks for new releases from monitored artists.
|
||||
- **Example:**
|
||||
```yaml
|
||||
scheduling:
|
||||
monitor_enabled: false
|
||||
```
|
||||
|
||||
#### `scheduling.monitor_interval_hours`
|
||||
- **Type:** integer
|
||||
- **Default:** `12`
|
||||
- **Description:** Hours between automatic monitor checks.
|
||||
- **Example:**
|
||||
```yaml
|
||||
scheduling:
|
||||
monitor_interval_hours: 24
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `subsonic` Section
|
||||
|
||||
Controls the Subsonic-compatible streaming API.
|
||||
|
||||
#### `subsonic.enabled`
|
||||
- **Type:** boolean
|
||||
- **Default:** `true`
|
||||
- **Description:** Whether the Subsonic API is active. The API is served at `/rest/*` on the same port as the web UI.
|
||||
- **Example:**
|
||||
```yaml
|
||||
subsonic:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
#### `subsonic.transcoding_enabled`
|
||||
- **Type:** boolean
|
||||
- **Default:** `true`
|
||||
- **Description:** Whether to transcode audio files (e.g., Opus to MP3) when streaming via the Subsonic API. Requires ffmpeg. Disable if your clients natively support your download format.
|
||||
- **Example:**
|
||||
```yaml
|
||||
subsonic:
|
||||
transcoding_enabled: false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `musicbrainz` Section
|
||||
|
||||
Controls the local MusicBrainz database for faster lookups.
|
||||
|
||||
#### `musicbrainz.local_db_path`
|
||||
- **Type:** string (file path) or null
|
||||
- **Default:** null (auto-detected at `{data_dir}/shanty-mb.db`)
|
||||
- **Description:** Path to the local MusicBrainz SQLite database. If not set and the file exists at the default location, it is used automatically. If not set and the file does not exist, only the remote MusicBrainz API is used.
|
||||
- **Example:**
|
||||
```yaml
|
||||
musicbrainz:
|
||||
local_db_path: /data/shanty-mb.db
|
||||
```
|
||||
|
||||
#### `musicbrainz.auto_update`
|
||||
- **Type:** boolean
|
||||
- **Default:** `false`
|
||||
- **Description:** Whether to automatically re-download and re-import MusicBrainz dumps on a weekly schedule.
|
||||
- **Example:**
|
||||
```yaml
|
||||
musicbrainz:
|
||||
auto_update: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Full Example Config
|
||||
|
||||
```yaml
|
||||
library_path: /music
|
||||
download_path: /data/downloads
|
||||
organization_format: "{artist}/{album}/{track_number} - {title}.{ext}"
|
||||
log_level: info
|
||||
|
||||
allowed_secondary_types:
|
||||
- Compilation
|
||||
|
||||
web:
|
||||
port: 8085
|
||||
bind: 0.0.0.0
|
||||
|
||||
tagging:
|
||||
write_tags: true
|
||||
confidence: 0.8
|
||||
|
||||
download:
|
||||
format: opus
|
||||
search_source: ytmusic
|
||||
rate_limit: 250
|
||||
rate_limit_auth: 1800
|
||||
|
||||
indexing:
|
||||
concurrency: 4
|
||||
|
||||
metadata:
|
||||
metadata_source: musicbrainz
|
||||
artist_image_source: wikipedia
|
||||
artist_bio_source: wikipedia
|
||||
lyrics_source: lrclib
|
||||
cover_art_source: coverartarchive
|
||||
|
||||
scheduling:
|
||||
pipeline_enabled: true
|
||||
pipeline_interval_hours: 3
|
||||
monitor_enabled: true
|
||||
monitor_interval_hours: 12
|
||||
|
||||
subsonic:
|
||||
enabled: true
|
||||
transcoding_enabled: true
|
||||
|
||||
musicbrainz:
|
||||
auto_update: false
|
||||
```
|
||||
@@ -0,0 +1,82 @@
|
||||
# Artist Monitoring
|
||||
|
||||
Monitoring lets Shanty automatically detect when your favorite artists release new music. When a new album or single is found, it is added to your watchlist and queued for download.
|
||||
|
||||
## How monitoring differs from watching
|
||||
|
||||
- **Watching** an artist means you have added some or all of their existing discography to your watchlist. Watched tracks go through the download pipeline.
|
||||
- **Monitoring** an artist means Shanty periodically checks MusicBrainz for new releases that were not in the artist's discography when you first added them. When something new appears, it is automatically added to your watchlist.
|
||||
|
||||
You can watch an artist without monitoring them (just download their existing catalog), and you can monitor a watched artist to stay up to date with new releases.
|
||||
|
||||
## How to set up
|
||||
|
||||
1. Open the Shanty web UI and navigate to an artist's page (search for them or open them from your library).
|
||||
2. Click the **Monitor** button on the artist page.
|
||||
3. The artist is now monitored. A badge indicates their monitoring status.
|
||||
|
||||
To stop monitoring an artist, click the **Monitor** button again to toggle it off.
|
||||
|
||||
## How it works
|
||||
|
||||
When monitoring is enabled, Shanty runs a background check on a schedule:
|
||||
|
||||
1. For each monitored artist, it fetches the current list of release groups from MusicBrainz.
|
||||
2. It compares this against the release groups already in the watchlist.
|
||||
3. Any new release groups (albums, singles, EPs) are expanded into individual track wanted_items and added to the watchlist.
|
||||
4. The artist's `last_checked_at` timestamp is updated.
|
||||
|
||||
If you have the pipeline scheduler enabled (the default), new releases are automatically downloaded on the next pipeline run.
|
||||
|
||||
## Automatic scheduling
|
||||
|
||||
Both the monitor check and the download pipeline run on configurable schedules:
|
||||
|
||||
| Task | Default interval | Config key |
|
||||
|------|-----------------|------------|
|
||||
| Monitor check | Every 12 hours | `scheduling.monitor_interval_hours` |
|
||||
| Pipeline (Set Sail) | Every 3 hours | `scheduling.pipeline_interval_hours` |
|
||||
|
||||
This means that in the default configuration:
|
||||
|
||||
1. The monitor checks for new releases every 12 hours.
|
||||
2. If new releases are found, they are added to the watchlist.
|
||||
3. Within 3 hours, the pipeline runs automatically, downloading and processing the new tracks.
|
||||
|
||||
## Configuring schedules
|
||||
|
||||
In your config file:
|
||||
|
||||
```yaml
|
||||
scheduling:
|
||||
pipeline_enabled: true
|
||||
pipeline_interval_hours: 3
|
||||
monitor_enabled: true
|
||||
monitor_interval_hours: 12
|
||||
```
|
||||
|
||||
Or adjust these settings in the web UI under **Settings**.
|
||||
|
||||
To disable automatic scheduling entirely:
|
||||
|
||||
```yaml
|
||||
scheduling:
|
||||
pipeline_enabled: false
|
||||
monitor_enabled: false
|
||||
```
|
||||
|
||||
When disabled, you can still trigger checks manually from the Dashboard.
|
||||
|
||||
## Manual checks
|
||||
|
||||
You can trigger a monitor check at any time from the Dashboard by clicking **Check Monitored** (under the system actions). The results show how many artists were checked, how many new releases were found, and how many tracks were added.
|
||||
|
||||
Similarly, you can trigger the pipeline manually by clicking **Set Sail** at any time.
|
||||
|
||||
## Viewing monitored artists
|
||||
|
||||
The monitoring status is visible on each artist's page. You can also check the current monitor status via the API at `GET /api/monitor/status`, which returns a list of all monitored artists with their last check timestamps.
|
||||
|
||||
## Skipping scheduled runs
|
||||
|
||||
If you want to skip the next scheduled pipeline or monitor run without disabling them permanently, you can do so from the Dashboard. The skip is a one-time action -- the schedule resumes after the skipped run.
|
||||
@@ -0,0 +1,80 @@
|
||||
# MusicBrainz Local Database
|
||||
|
||||
MusicBrainz is the source of all music metadata in Shanty: artist information, album listings, track listings, and release data. By default, Shanty queries the MusicBrainz API over the internet, which is rate-limited to 1 request every 1.1 seconds.
|
||||
|
||||
Importing the MusicBrainz database locally eliminates this bottleneck for most lookups.
|
||||
|
||||
## What this does
|
||||
|
||||
The import downloads a full copy of the MusicBrainz database (as JSON dumps) and loads it into a local SQLite database on your machine. When Shanty needs to look up an artist's discography, release track listings, or recording details, it checks the local database first. If the data is found locally, the response is instant. If not (for example, very new releases), it falls back to the remote API.
|
||||
|
||||
## Why you might want this
|
||||
|
||||
Without the local database, browsing a new artist's full discography requires many API calls (one per release group, one per release to get track listings). With the rate limit, loading an artist with 15 albums can take 30-60 seconds.
|
||||
|
||||
With the local database, the same operation completes in under a second.
|
||||
|
||||
If you are casually using Shanty for a few artists, the caching system works well enough without the local database. But if you frequently browse and add new artists, the local database makes the experience dramatically faster.
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Download size:** approximately 24 GB (compressed JSON dumps from MusicBrainz)
|
||||
- **Database size:** approximately 16 GB (the resulting SQLite database)
|
||||
- **Disk type:** SSD strongly recommended. The import writes millions of rows, which is very slow on spinning disks.
|
||||
- **Time:** 12-24 hours for the initial import, depending on your hardware and disk speed.
|
||||
- **Disk space total:** You need roughly 40 GB free during import (dumps + database). After import, you can delete the dump files to reclaim the 24 GB.
|
||||
|
||||
## How to set up via the web UI
|
||||
|
||||
1. Open the Shanty web UI and go to **Settings**.
|
||||
2. Scroll to the **MusicBrainz Database** section.
|
||||
3. Click **Import**.
|
||||
4. Shanty downloads the dump files and imports them. Progress is shown on the Dashboard.
|
||||
|
||||
You can continue using Shanty while the import runs. It will use the remote API until the import completes.
|
||||
|
||||
## How to set up via the CLI
|
||||
|
||||
If you prefer the command line (or want to run the import on a more powerful machine):
|
||||
|
||||
```sh
|
||||
# Inside Docker
|
||||
docker compose exec shanty ./shanty mb-import --download
|
||||
|
||||
# From source
|
||||
cargo run --release --bin shanty -- mb-import --download
|
||||
```
|
||||
|
||||
Options:
|
||||
- `--download` -- Download fresh dump files from metabrainz.org before importing. Without this flag, the import looks for existing dump files in the data directory.
|
||||
- `--data-dir /path/to/dumps` -- Custom directory for dump files. Defaults to `{data_dir}/mb-dumps`.
|
||||
|
||||
The database is created at `{data_dir}/shanty-mb.db` by default. You can override this with the `musicbrainz.local_db_path` config option.
|
||||
|
||||
## Automatic weekly updates
|
||||
|
||||
MusicBrainz publishes new database dumps regularly. You can configure Shanty to automatically re-download and re-import them:
|
||||
|
||||
```yaml
|
||||
musicbrainz:
|
||||
auto_update: true
|
||||
```
|
||||
|
||||
When enabled, Shanty checks weekly for new dumps and runs the import in the background if a newer dump is available. The existing local database continues to serve queries during the update.
|
||||
|
||||
## The hybrid approach
|
||||
|
||||
Shanty uses what it calls a "hybrid fetcher":
|
||||
|
||||
1. **Local database** is checked first for any MusicBrainz lookup (artist info, release groups, track listings, etc.).
|
||||
2. **Remote API** is used as a fallback when data is not in the local database (new releases added after the last import, for example).
|
||||
3. **Cache** is used for data that was fetched from the remote API, so repeated lookups do not hit the rate limit.
|
||||
|
||||
This means you get the best of both worlds: instant lookups for the vast majority of music that exists in the database dumps, and up-to-date data for newly released music via the API.
|
||||
|
||||
## Configuration options
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `musicbrainz.local_db_path` | `{data_dir}/shanty-mb.db` | Path to the local SQLite database |
|
||||
| `musicbrainz.auto_update` | `false` | Automatically re-import dumps weekly |
|
||||
@@ -0,0 +1,92 @@
|
||||
# Playlists
|
||||
|
||||
Shanty can generate playlists from your library using similar-artist data from Last.fm. You can also create and edit playlists manually, export them as M3U files, and access them from Subsonic clients.
|
||||
|
||||
## Requirements
|
||||
|
||||
Playlist generation using the **similar-artist** strategy requires a Last.fm API key. Set it via the `SHANTY_LASTFM_API_KEY` environment variable:
|
||||
|
||||
```yaml
|
||||
# In docker-compose.yml
|
||||
environment:
|
||||
- SHANTY_LASTFM_API_KEY=your_api_key_here
|
||||
```
|
||||
|
||||
Get a free API key at: https://www.last.fm/api/account/create
|
||||
|
||||
Other playlist strategies (genre, random, smart rules) do not require an API key.
|
||||
|
||||
## Generating a playlist
|
||||
|
||||
1. Open the Shanty web UI and go to **Playlists**.
|
||||
2. Click the **Generate** tab.
|
||||
3. Choose a generation strategy:
|
||||
- **Similar Artists** -- Start with one or more seed artists and build a playlist from their music and music by similar artists. This is the most useful strategy for discovering connections in your library.
|
||||
- **Genre** -- Filter tracks by genre tags.
|
||||
- **Random** -- A random selection from your library.
|
||||
- **Smart Rules** -- Define rules based on track attributes (artist, album, year, genre, etc.).
|
||||
4. For the Similar Artists strategy:
|
||||
- Search for and select one or more **seed artists**.
|
||||
- Adjust **popularity bias** (higher values favor well-known tracks, lower values dig deeper).
|
||||
- Set the **track count** (how many tracks in the playlist).
|
||||
- Choose **ordering**: interleave (mix artists evenly), score (highest match first), or random.
|
||||
5. Click **Generate**.
|
||||
|
||||
The generated playlist is shown as a preview. You can then save it or adjust the parameters and regenerate.
|
||||
|
||||
## Saving a playlist
|
||||
|
||||
After generating a playlist, click **Save** to give it a name and store it. Saved playlists appear in the **Saved** tab.
|
||||
|
||||
## Editing a playlist
|
||||
|
||||
1. Go to the **Saved** tab in Playlists.
|
||||
2. Click **Edit** on a playlist.
|
||||
3. In the Edit tab, you can:
|
||||
- **Drag and drop** tracks to reorder them.
|
||||
- **Remove** tracks by clicking the remove button next to each track.
|
||||
- **Add** tracks by searching in the track picker at the bottom.
|
||||
- **Rename** the playlist or update its description.
|
||||
|
||||
## Exporting as M3U
|
||||
|
||||
To export a playlist as an M3U file (compatible with most music players):
|
||||
|
||||
1. Open a saved playlist.
|
||||
2. Click **Export M3U**.
|
||||
3. The file downloads to your computer.
|
||||
|
||||
M3U files contain file paths relative to your library, so they work with any music player that has access to the same library directory.
|
||||
|
||||
## Playlists via Subsonic
|
||||
|
||||
Saved playlists are available through the Subsonic API. Any Subsonic client that supports playlists (most do) can see and play your Shanty playlists.
|
||||
|
||||
To use this, make sure you have [Subsonic set up](subsonic.md) with a Subsonic password configured.
|
||||
|
||||
## Generation strategies explained
|
||||
|
||||
### Similar Artists
|
||||
|
||||
This uses Last.fm's similar-artist data to find tracks from artists related to your seeds. For example, if you seed with "Radiohead," the playlist might include tracks by Radiohead, Thom Yorke, Portishead, Massive Attack, and other similar artists -- but only tracks that exist in your library.
|
||||
|
||||
The **popularity bias** slider controls the balance:
|
||||
- High bias (closer to 1.0): favors popular/well-known tracks
|
||||
- Low bias (closer to 0.0): gives equal weight to all tracks
|
||||
|
||||
### Genre
|
||||
|
||||
Filters your library by genre tags and selects tracks that match. You can specify one or more genres.
|
||||
|
||||
### Random
|
||||
|
||||
A random sample from your entire library. If ordering is not set to "random," tracks are ordered by artist/album for easier listening.
|
||||
|
||||
### Smart Rules
|
||||
|
||||
Define custom rules like:
|
||||
- Artist contains "Pink Floyd"
|
||||
- Year is between 1970 and 1980
|
||||
- Genre is "Progressive Rock"
|
||||
|
||||
Tracks matching all rules are included, up to the count limit.
|
||||
@@ -0,0 +1,94 @@
|
||||
# Subsonic Streaming
|
||||
|
||||
Shanty includes a Subsonic-compatible API that lets you stream your music library to mobile apps, desktop players, and other Subsonic clients.
|
||||
|
||||
## What is Subsonic?
|
||||
|
||||
Subsonic is a widely-supported protocol for streaming music from a personal server. Many music apps implement the Subsonic API, which means you can use any of them to stream your Shanty library to your phone, tablet, or desktop.
|
||||
|
||||
## Important note
|
||||
|
||||
Shanty implements a subset of the Subsonic API -- enough for browsing, streaming, playlists, and search. If you need a full-featured Subsonic server with advanced features like sharing, podcasts, or Internet radio, consider running [Navidrome](https://www.navidrome.org/) pointed at the same music library directory. Both can coexist.
|
||||
|
||||
## How to set up
|
||||
|
||||
### 1. Set a Subsonic password
|
||||
|
||||
The Subsonic protocol uses its own authentication system, separate from your Shanty web login.
|
||||
|
||||
1. Open the Shanty web UI and go to **Settings**.
|
||||
2. Find the **Subsonic API** section.
|
||||
3. Enter a password and click **Save**.
|
||||
|
||||
**Security note:** The Subsonic protocol transmits passwords as MD5 hashes (not encrypted). This is a limitation of the protocol itself. Do not reuse a password you use for other services. The Subsonic password is stored in plain text in the database, per the protocol specification.
|
||||
|
||||
### 2. Configure your client
|
||||
|
||||
In your Subsonic client app, add a new server with these settings:
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Server URL** | `http://your-server-ip:8085` |
|
||||
| **Username** | Your Shanty username |
|
||||
| **Password** | The Subsonic password you set (not your web login password) |
|
||||
|
||||
Most clients automatically append `/rest` to the server URL. If your client asks for just the base URL, enter `http://your-server-ip:8085`.
|
||||
|
||||
If your client has separate fields for server address and port, enter the IP/hostname and `8085` separately.
|
||||
|
||||
### 3. Test the connection
|
||||
|
||||
Most clients have a "Test Connection" button. Use it to verify that the server is reachable and your credentials are correct.
|
||||
|
||||
## Recommended clients
|
||||
|
||||
These clients have been tested with Shanty's Subsonic implementation:
|
||||
|
||||
### Android
|
||||
- **[Ultrasonic](https://f-droid.org/packages/org.moire.ultrasonic/)** -- Free and open source. Available on F-Droid and Google Play. Reliable and well-maintained.
|
||||
- **[DSub](https://play.google.com/store/apps/details?id=github.daneren2005.dsub)** -- Feature-rich, supports offline caching.
|
||||
- **[Symfonium](https://play.google.com/store/apps/details?id=app.symfonik.music.player)** -- Modern UI, excellent playback features. Paid app.
|
||||
|
||||
### Desktop
|
||||
- **[Feishin](https://github.com/jeffvli/feishin)** -- Cross-platform desktop client with a modern interface. Free and open source.
|
||||
|
||||
## Supported Subsonic endpoints
|
||||
|
||||
Shanty implements these Subsonic API endpoints:
|
||||
|
||||
- **System:** `ping`, `getLicense`
|
||||
- **Browsing:** `getMusicFolders`, `getIndexes`, `getMusicDirectory`, `getArtists`, `getArtist`, `getAlbum`, `getSong`, `getGenres`
|
||||
- **Search:** `search3`
|
||||
- **Media:** `stream`, `download`, `getCoverArt`
|
||||
- **Playlists:** `getPlaylists`, `getPlaylist`, `createPlaylist`, `deletePlaylist`
|
||||
- **Annotation:** `scrobble`
|
||||
- **User:** `getUser`
|
||||
|
||||
## Transcoding
|
||||
|
||||
If your music is in Opus format (the default download format), many mobile clients cannot play it directly. Shanty automatically transcodes Opus files to MP3 when streaming via the Subsonic API. This requires ffmpeg, which is included in the Docker image.
|
||||
|
||||
If you download in MP3 format or your clients support Opus natively, you can disable transcoding:
|
||||
|
||||
```yaml
|
||||
subsonic:
|
||||
transcoding_enabled: false
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**"Authentication failed" in client:**
|
||||
- Make sure you are using the Subsonic password, not your web login password.
|
||||
- Make sure the username matches exactly (case-sensitive).
|
||||
|
||||
**Client cannot connect:**
|
||||
- Verify the server URL includes the port (`http://ip:8085`, not just `http://ip`).
|
||||
- Check that port 8085 is accessible from the device (firewall rules, same network, etc.).
|
||||
|
||||
**No music showing up:**
|
||||
- Music must be organized in the library (run the pipeline at least once) to appear in the Subsonic API.
|
||||
- Only tracks with file paths in the database are served.
|
||||
|
||||
**Audio does not play:**
|
||||
- If using Opus format, make sure transcoding is enabled (it is by default).
|
||||
- Check that ffmpeg is installed (included in Docker, must be installed manually for source builds).
|
||||
@@ -0,0 +1,72 @@
|
||||
# YouTube Authentication
|
||||
|
||||
Shanty downloads music from YouTube via yt-dlp. By default, it makes requests as a guest, which limits you to roughly 250 downloads per hour. Authenticating with a Google account increases this to roughly 1800 downloads per hour and grants access to age-restricted content.
|
||||
|
||||
## Should you set this up?
|
||||
|
||||
If you are downloading just a few albums at a time, guest mode is fine. If you are adding several artists at once or building a large library, authentication will save you a lot of waiting.
|
||||
|
||||
## Warning: Use a throwaway account
|
||||
|
||||
There is a small but real risk that Google may flag your account for unusual activity. Automated downloading is against YouTube's terms of service. To protect yourself:
|
||||
|
||||
- Create a new Google account specifically for this purpose.
|
||||
- Do not use your main Google account.
|
||||
- Do not use an account tied to important services (Gmail, Google Drive, etc.).
|
||||
|
||||
## How to set up
|
||||
|
||||
1. Open the Shanty web UI and go to **Settings**.
|
||||
2. Scroll to the **YouTube Authentication** section.
|
||||
3. Click **Authenticate**.
|
||||
4. A noVNC browser window opens, showing Firefox inside the Shanty container.
|
||||
5. Navigate to YouTube and log in with your throwaway Google account.
|
||||
6. Once you are logged in, go back to the Shanty settings page and click **Done**.
|
||||
|
||||
Shanty extracts the YouTube cookies from Firefox and saves them. From this point forward, all downloads use your authenticated session.
|
||||
|
||||
## Docker port requirement
|
||||
|
||||
The noVNC interface runs on port **6080** by default. Your `docker-compose.yml` must expose this port:
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "8085:8085"
|
||||
- "6080:6080" # Required for YouTube login
|
||||
```
|
||||
|
||||
If you are running Shanty on a remote server, you need to access noVNC from your browser at `http://your-server-ip:6080`. Make sure firewalls allow this port during the login process. You can close the port afterward if you want -- it is only needed during initial login and manual re-authentication.
|
||||
|
||||
The noVNC port is configurable via `download.vnc_port` in the config file.
|
||||
|
||||
## How auto-refresh works
|
||||
|
||||
YouTube cookies expire roughly every 2 weeks. Shanty automatically refreshes them using headless Firefox (no visible browser window needed):
|
||||
|
||||
- After you complete the login process, auto-refresh is enabled automatically.
|
||||
- Every 6 hours (configurable via `download.cookie_refresh_hours`), Shanty launches Firefox in headless mode, loads YouTube using the saved profile, and exports fresh cookies.
|
||||
- If a refresh fails, Shanty logs a warning and tries again at the next interval.
|
||||
|
||||
You can check the current cookie status in **Settings** under **YouTube Authentication**. It shows whether cookies are present, how old they are, and whether auto-refresh is enabled.
|
||||
|
||||
## Manual refresh
|
||||
|
||||
If cookies have expired and auto-refresh is not working, you can:
|
||||
|
||||
1. Click **Refresh** in the YouTube Authentication settings to trigger an immediate headless refresh.
|
||||
2. If that fails, click **Authenticate** to log in again through noVNC.
|
||||
|
||||
## Clearing cookies
|
||||
|
||||
To remove all YouTube authentication data, click **Clear** in the YouTube Authentication settings. This deletes the cookies file and the Firefox profile, and disables auto-refresh.
|
||||
|
||||
## Configuration options
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `download.cookies_path` | (auto) | Path to the cookies file. Managed automatically. |
|
||||
| `download.cookie_refresh_enabled` | `false` | Auto-enabled after login. |
|
||||
| `download.cookie_refresh_hours` | `6` | Hours between refresh attempts. |
|
||||
| `download.rate_limit` | `250` | Requests/hour without cookies. |
|
||||
| `download.rate_limit_auth` | `1800` | Requests/hour with cookies. |
|
||||
| `download.vnc_port` | `6080` | Port for the noVNC login interface. |
|
||||
@@ -0,0 +1,149 @@
|
||||
# Getting Started
|
||||
|
||||
This guide walks you through setting up Shanty from scratch. By the end, you will have a running instance that can search for music, download it, and play it on your phone.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need Docker and Docker Compose installed on your computer or server. If you do not have them:
|
||||
|
||||
- **Linux:** Follow the [Docker install guide](https://docs.docker.com/engine/install/) for your distribution.
|
||||
- **Mac/Windows:** Install [Docker Desktop](https://www.docker.com/products/docker-desktop/).
|
||||
|
||||
You also need a folder where you want your music library stored.
|
||||
|
||||
## Step 1: Create a docker-compose.yml
|
||||
|
||||
Create a new folder for your Shanty configuration, then create a file called `docker-compose.yml` inside it:
|
||||
|
||||
```sh
|
||||
mkdir shanty && cd shanty
|
||||
```
|
||||
|
||||
Create `docker-compose.yml` with these contents:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
shanty:
|
||||
image: git.squid-inc.dev/connor/shanty:latest
|
||||
ports:
|
||||
- "8085:8085"
|
||||
- "6080:6080"
|
||||
volumes:
|
||||
- ./config:/config
|
||||
- shanty-data:/data
|
||||
- /path/to/your/music:/music
|
||||
environment:
|
||||
- SHANTY_WEB_BIND=0.0.0.0
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
shanty-data:
|
||||
```
|
||||
|
||||
Replace `/path/to/your/music` with the actual path to where you want your music stored. For example, `/home/yourname/Music` on Linux or `/Users/yourname/Music` on Mac.
|
||||
|
||||
### What the volumes do
|
||||
|
||||
| Mount point | Purpose |
|
||||
|-------------|---------|
|
||||
| `./config` | Stores your configuration file (`config.yaml`). Lives next to your docker-compose.yml. |
|
||||
| `shanty-data` | Stores the database and downloaded files before they are organized. Managed by Docker. |
|
||||
| `/music` | Your music library. This is where organized, tagged music ends up. |
|
||||
|
||||
## Step 2: Start the container
|
||||
|
||||
From the folder containing your `docker-compose.yml`:
|
||||
|
||||
```sh
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Wait a few seconds for the container to start. You can check the logs with:
|
||||
|
||||
```sh
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
You should see a line like `starting server bind=0.0.0.0:8085`. Press Ctrl+C to stop watching logs (the container keeps running).
|
||||
|
||||
## Step 3: Create your account
|
||||
|
||||
Open your browser and go to:
|
||||
|
||||
```
|
||||
http://localhost:8085
|
||||
```
|
||||
|
||||
If Shanty is running on another machine, replace `localhost` with that machine's IP address.
|
||||
|
||||
On first launch, you will see a setup screen. Choose a username and password (at least 4 characters). This creates an admin account.
|
||||
|
||||
## Step 4: Search and watch an artist
|
||||
|
||||
1. Click the **Search** tab in the navigation.
|
||||
2. Type an artist name (for example, "Pink Floyd") and press Enter.
|
||||
3. Click on the artist in the search results to view their discography.
|
||||
4. Click **Watch All** to add their entire discography to your watchlist. Or click individual albums to watch specific ones.
|
||||
|
||||
You will see the artist appear on the **Library** page with track counts showing how many tracks are wanted versus owned.
|
||||
|
||||
## Step 5: Download your music
|
||||
|
||||
Click the **Set Sail** button on the Dashboard. This runs the full pipeline:
|
||||
|
||||
1. **Sync** -- creates download jobs for all wanted tracks
|
||||
2. **Download** -- fetches audio from YouTube Music via yt-dlp
|
||||
3. **Tag** -- writes MusicBrainz metadata to the files
|
||||
4. **Organize** -- moves files into your music library in a clean folder structure
|
||||
|
||||
You can watch progress on the Dashboard. The download queue shows each track as it is processed.
|
||||
|
||||
Depending on how many tracks you are downloading, this can take a while. YouTube has rate limits (roughly 250 downloads per hour without authentication). See the [YouTube Authentication](features/youtube-auth.md) guide to increase this to roughly 1800 per hour.
|
||||
|
||||
## Step 6 (Optional): Set up Subsonic for mobile playback
|
||||
|
||||
Shanty includes a Subsonic-compatible API that lets you stream your library from mobile apps like Ultrasonic, DSub, or Symfonium.
|
||||
|
||||
1. In the Shanty web UI, go to **Settings**.
|
||||
2. Find the **Subsonic API** section.
|
||||
3. Set a Subsonic password. This is separate from your web login password.
|
||||
4. On your phone, install a Subsonic client (Ultrasonic for Android is free and works well).
|
||||
5. In the client, add a server with the URL `http://your-server-ip:8085`. The client adds `/rest` automatically.
|
||||
6. Enter your Shanty username and the Subsonic password you just set.
|
||||
|
||||
See the [Subsonic guide](features/subsonic.md) for more details and recommended clients.
|
||||
|
||||
## Step 7 (Optional): Set up YouTube authentication
|
||||
|
||||
Without authentication, YouTube limits you to roughly 250 downloads per hour. With authentication, this increases to roughly 1800 per hour. You also get access to age-restricted content.
|
||||
|
||||
1. Go to **Settings** in the Shanty web UI.
|
||||
2. Find the **YouTube Authentication** section and click **Authenticate**.
|
||||
3. A browser window opens in your browser via noVNC. Log in to a Google account.
|
||||
4. Click **Done** when finished.
|
||||
|
||||
**Important:** Use a throwaway Google account. There is a small risk of account restrictions. See the [YouTube Authentication guide](features/youtube-auth.md) for details.
|
||||
|
||||
## Step 8 (Optional): Import the MusicBrainz database
|
||||
|
||||
MusicBrainz has a rate limit of 1 request every 1.1 seconds. When you browse a new artist, loading their full discography can take 30-60 seconds. Importing the MusicBrainz database locally makes these lookups instant.
|
||||
|
||||
This requires about 24 GB of download space, produces a 16 GB database, and takes 12-24 hours for the initial import. An SSD is strongly recommended.
|
||||
|
||||
To start the import from the web UI:
|
||||
1. Go to **Settings**.
|
||||
2. Find the **MusicBrainz Database** section.
|
||||
3. Click **Import**.
|
||||
|
||||
Or from the command line:
|
||||
```sh
|
||||
docker compose exec shanty ./shanty mb-import --download
|
||||
```
|
||||
|
||||
See the [MusicBrainz Database guide](features/musicbrainz-db.md) for more details.
|
||||
|
||||
## What next?
|
||||
|
||||
- Set up [monitoring](features/monitoring.md) to automatically detect new releases from your favorite artists.
|
||||
- Generate [playlists](features/playlists.md) from your library using similar-artist data.
|
||||
- Check the [Configuration Reference](configuration.md) to customize download formats, organization templates, and scheduling.
|
||||
Reference in New Issue
Block a user