d756aab7fc
Two bugs conspired to fill the library with .1.flac duplicates on the night of 2026-07-15/16: 1. sldl derives its skip-index folder from the input: the Spotify playlist display name before 0.6.2, the CSV filename after. The switch stranded every playlist's download history in the old emoji-named subfolder, so sldl started from an empty index and re-downloaded every playlist in full. Fix: pin index-path in _template.conf, seed the pinned file from all stranded indexes (merge-sldl-indexes.py, called from run-playlist.sh whenever the pinned index is missing or older than a stranded one). Recovered rows keep the CSV-era identity fields but are marked downloaded, so tracks that failed last night yet exist in the library since months ago are not fetched again. 2. The safety net that should have flagged the flood, dedup-library.sh, has silently reported 0 groups since the 2026-07-08 path rewrite: host_path() still assumed /music/... display paths and prepended the library dir to already-correct /data/music/Library/... paths, so every candidate failed the -f check. Fix: pass real paths through unchanged, keep the /music prefix swap only for legacy entries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
89 lines
3.6 KiB
Plaintext
89 lines
3.6 KiB
Plaintext
# Template for per-playlist sldl configs (sldl 2.6.0.0).
|
|
# Flags verified against `sldl --help` output.
|
|
#
|
|
# sldl runs as a subprocess inside the alembic container (same container as
|
|
# beets, on gluetun's network namespace for VPN-routed Soulseek P2P).
|
|
|
|
# This is a TEMPLATE. The app renders one <playlist>.conf per playlist from it
|
|
# (credential_service.render_playlist_confs), substituting PLAYLIST_NAME,
|
|
# SPOTIFY_URL, SLDL_DROPBOX_ROOT and the credential lines below in one pass.
|
|
# The placeholder values here are overwritten at render time; edit the
|
|
# non-placeholder settings (quality, timeouts, ports) to change every playlist.
|
|
|
|
# ==== Soulseek credentials ====
|
|
user = SOULSEEK_USER
|
|
pass = SOULSEEK_PASS
|
|
|
|
# ==== Input (Spotify playlist URL) ====
|
|
# sldl itself never reads Spotify at all -- its vendored Spotify client still
|
|
# calls GET /playlists/{id}/tracks, which Spotify removed in its February 2026
|
|
# API changes (new apps get a hard 403 there regardless of auth method; see
|
|
# spotify-playlist-csv.py). run-playlist.sh reads the playlist itself (via the
|
|
# still-working /items endpoint) and hands sldl a CSV via --input-type csv on
|
|
# the command line, which overrides this line entirely -- it's kept only so
|
|
# run-playlist.sh has somewhere to read the playlist URL from per-playlist.
|
|
input = SPOTIFY_URL
|
|
|
|
# ==== Output paths ====
|
|
# SLDL_DROPBOX_ROOT is substituted at render time from $MUSIC_DATA_DIR
|
|
# (sldl's own config format has no env-var expansion).
|
|
path = SLDL_DROPBOX_ROOT/PLAYLIST_NAME
|
|
playlist-path = SLDL_DROPBOX_ROOT/PLAYLIST_NAME/_sldl.m3u8
|
|
write-playlist = true
|
|
|
|
# ==== Skip index (pinned!) ====
|
|
# sldl's already-downloaded index defaults to {path}/{playlist-name}/_index.csv
|
|
# where {playlist-name} is derived from the INPUT: the Spotify playlist's
|
|
# display name for spotify input, the CSV filename for csv input. beets moves
|
|
# every download out of the dropbox, so this index is the ONLY thing standing
|
|
# between a nightly run and re-downloading the whole playlist. When 0.6.2
|
|
# switched input from Spotify URL to CSV, the derived name changed, sldl
|
|
# started a fresh empty index in a new subfolder, and every playlist
|
|
# re-downloaded in full on 2026-07-16. Pinning the path here decouples the
|
|
# index from input naming so that can never happen again.
|
|
index-path = SLDL_DROPBOX_ROOT/PLAYLIST_NAME/_index.csv
|
|
|
|
# ==== Naming ====
|
|
name-format = {artist} - {title}
|
|
|
|
# ==== Concurrent downloads ====
|
|
# Higher values download from more peers simultaneously.
|
|
# Each peer is usually ~100-500 KB/s, so 10 concurrent ≈ 1-5 MB/s total.
|
|
# Bandwidth isn't the bottleneck on Soulseek - peer availability is.
|
|
concurrent-downloads = 10
|
|
|
|
# ==== Search behavior ====
|
|
fast-search = true
|
|
search-timeout = 60000
|
|
max-stale-time = 50000
|
|
searches-per-time = 34
|
|
searches-renew-time = 220
|
|
|
|
# ==== Soulseek listen port ====
|
|
# Picking a port that:
|
|
# - is below Linux's ephemeral range (32768-60999), so the OS won't auto-pick
|
|
# it for slskd's outbound peer connections;
|
|
# - is NOT one of slskd's bound ports inside gluetun (slskd uses 5030 HTTP,
|
|
# 5031 HTTPS, 50300 Soulseek listen);
|
|
# - is NOT used by any other gluetun-network container (qbittorrent: 6881,
|
|
# shelfmark: 8084).
|
|
# 9876 fits all three.
|
|
listen-port = 9876
|
|
|
|
# ==== Quality hard filters (strict - files not matching are rejected) ====
|
|
format = flac,mp3
|
|
min-bitrate = 320
|
|
|
|
# ==== Quality preferences (soft - controls ranking among accepted files) ====
|
|
pref-format = flac,wav,mp3
|
|
pref-min-bitrate = 320
|
|
pref-max-bitrate = 2500
|
|
|
|
# ==== Strict filtering (hard - rejects files that don't match) ====
|
|
strict-title = true
|
|
strict-artist = true
|
|
|
|
# ==== Misc ====
|
|
verbose = true
|
|
no-browse-folder = true
|