{"id":48502709,"url":"https://github.com/fiso64/sldl","last_synced_at":"2026-04-07T15:30:53.397Z","repository":{"id":147535061,"uuid":"618633776","full_name":"fiso64/sldl","owner":"fiso64","description":"Advanced download tool for Soulseek.","archived":false,"fork":false,"pushed_at":"2026-03-24T14:27:16.000Z","size":841,"stargazers_count":848,"open_issues_count":23,"forks_count":57,"subscribers_count":11,"default_branch":"master","last_synced_at":"2026-03-25T18:35:54.495Z","etag":null,"topics":["cli","command-line-tool","soulseek","soulseek-network"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fiso64.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-24T22:59:28.000Z","updated_at":"2026-03-24T22:29:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"228f7b0c-b43d-4428-88dd-872b8b573974","html_url":"https://github.com/fiso64/sldl","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/fiso64/sldl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiso64%2Fsldl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiso64%2Fsldl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiso64%2Fsldl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiso64%2Fsldl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fiso64","download_url":"https://codeload.github.com/fiso64/sldl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiso64%2Fsldl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31518377,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","command-line-tool","soulseek","soulseek-network"],"created_at":"2026-04-07T15:30:51.687Z","updated_at":"2026-04-07T15:30:53.381Z","avatar_url":"https://github.com/fiso64.png","language":"C#","readme":"# sldl\n\nA smart and configurable downloader for Soulseek. Built with Soulseek.NET.\n\n### Features\n\n- Accepts various input sources like CSV files, Spotify or YouTube URLs, or standard text queries\n- Can download individual songs, playlists, albums, or full artist discographies\n- Intelligently selects the best album or song based on user configuration and heuristics\n- For those who don't trust full auto downloading, album downloads can be [interactive](#shortcuts--interactive-mode). The best results will be listed first.\n- Special \"aggregate\" modes which can list all distinct songs or albums by a given artist available on Soulseek, sorted by popularity\n- Can skip downloading songs or albums found in a given music directory\n- Configuration profiles and auto profiles\n- Arbitratry name formatting for downloaded files\n- On-complete commands that can run when a download succeeds or fails\n\n## Setup\n\n1. Head to the [releases](https://github.com/fiso64/slsk-batchdl/releases) page and get an appropriate release for your system.\n2. Put your soulseek username and password in the [configuration file](#configuration).\n3. Try it:\n    ```bash\n    sldl \"Artist - Your Favorite Album\" -at\n    ```\n    This will search for the album and show an interactive UI for result selection.  \n    For more examples, see the [usage examples section](#examples-2).\n\n## Important\n\u003e [!NOTE]\n\u003e `sldl` doesn't share your music folders by itself. To keep the Soulseek network healthy over the long term, please also share your collection using a regular client like [Nicotine+](https://github.com/nicotine-plus/nicotine-plus) or [slskd](https://github.com/slskd/slskd). \n\n\u003e [!NOTE]\n\u003e Because it's not possible to run the same account on two separate clients simultaneously, it is recommended to use `sldl` with a **separate Soulseek account** to avoid connection problems.\n\n## Index\n - [Options](#options)\n - [Input types](#input-types)\n   - [CSV file](#csv-file)\n   - [YouTube](#youtube)\n   - [Spotify](#spotify)\n   - [Bandcamp](#bandcamp)\n   - [MusicBrainz](#musicbrainz)\n   - [Soulseek Link](#soulseek-link)\n   - [Search string](#search-string)\n   - [List file](#list-file)\n - [Download modes](#download-modes)\n   - [Normal](#normal)\n   - [Album](#album)\n   - [Aggregate](#aggregate)\n   - [Album Aggregate](#album-aggregate)\n - [Configuration](#configuration)\n - [File conditions](#file-conditions)\n - [Name format](#name-format)\n - [On-Complete Actions](#on-complete-actions)\n - [Shortcuts \\\u0026 interactive mode](#shortcuts--interactive-mode)\n - [Examples](#examples-2)\n - [Notes](#notes-1)\n - [Tips](#tips)\n - [Docker](#docker)\n\n\n## Options\n\u003c!-- sldl-help:start(main) --\u003e\n#### Required Arguments\n```\n\u003cinput\u003e                         A url, search string, or path to a local CSV file.\n                                Run `--help input` to view the accepted inputs.\n                                Can also be passed with -i, --input \u003cinput\u003e\n--user \u003cusername\u003e               Soulseek username\n--pass \u003cpassword\u003e               Soulseek password\n```\n#### General Options\n```\n-p, --path \u003cpath\u003e               Download directory\n--input-type \u003ctype\u003e             [csv|youtube|spotify|bandcamp|string|list] (default: auto)\n--name-format \u003cformat\u003e          Name format for downloaded tracks. See `--help name-format`\n    \n-n, --number \u003cmaxtracks\u003e        Download the first n tracks of a playlist\n-o, --offset \u003coffset\u003e           Skip a specified number of tracks\n-r, --reverse                   Download tracks in reverse order\n-c, --config \u003cpath\u003e             Set config file location. Set to 'none' to ignore config\n--profile \u003cnames\u003e               Configuration profile(s) to use. See `--help config`.\n--concurrent-downloads \u003cnum\u003e    Max concurrent downloads for normal mode (default: 2)\n--write-playlist                Create an m3u playlist file in the output directory\n--playlist-path \u003cpath\u003e          Override default path for m3u playlist file\n--no-incomplete-ext             Save files with their final name instead of a temporary\n                                `.incomplete` extension.\n    \n--no-skip-existing              Do not skip downloaded tracks\n--no-write-index                Do not create a file indexing all downloaded tracks\n--index-path \u003cpath\u003e             Override default path for sldl index\n--skip-check-cond               Check file conditions when skipping existing files\n--skip-check-pref-cond          Check preferred conditions when skipping existing files  \n--skip-music-dir \u003cpath\u003e         Also skip downloading tracks found in a music library by\n                                comparing filenames. Not 100% reliable.\n--skip-not-found                Skip searching for tracks that weren't found on Soulseek\n                                during the last run.\n    \n--listen-port \u003cport\u003e            Port for incoming connections (default: 49998)\n--connect-timeout \u003cms\u003e          Timeout used when logging in to Soulseek (default: 20000ms)\n--user-description \u003cdesc\u003e       Optional description text for your Soulseek account\n--shared-files \u003cint\u003e            Number of files you share on Soulseek (default: 0)\n--shared-folders \u003cint\u003e          Number of folders you share on Soulseek (default: 0)\n\n--on-complete \u003ccommand\u003e         Run a command when a download completes. See `--help\n                                on-complete`\n```\n#### Search Options\n```\n--fast-search                   Begin downloading as soon as a file satisfying the preferred\n                                conditions is found. Only for normal download mode.\n--remove-ft                     Remove 'feat.' and everything after before searching\n--regex \u003cregex\u003e                 Remove a regexp from all track titles and artist names.\n                                Optionally specify a replacement regex after a semicolon.\n                                Add 'T:', 'A:' or 'L:' at the start to only apply this to\n                                the track title, artist, or album respectively.\n--artist-maybe-wrong            Performs an additional search without the artist name.\n                                Useful for sources like SoundCloud where the \"artist\"\n                                could just be an uploader. Note that when downloading a\n                                YouTube playlist via url, this option is set automatically\n                                on a per-track basis, so it is best kept off in that case.\n-d, --desperate                 Tries harder to find the desired track by searching for the\n                                artist/album/title only, then filtering. (slower search)\n--fails-to-downrank \u003cnum\u003e       Number of fails to downrank a user's shares (default: 1)\n--fails-to-ignore \u003cnum\u003e         Number of fails to ban/ignore a user's shares (default: 2)\n\n--yt-dlp                        Use yt-dlp to download tracks that weren't found on\n                                Soulseek. yt-dlp must be available from the command line.\n--yt-dlp-argument \u003cstr\u003e         The command line arguments when running yt-dlp. Default:\n                                \"{id}\" -f bestaudio/best -cix -o \"{savepath}.%(ext)s\"\n                                Available vars are: {id}, {savedir}, {savepath} (w/o ext).\n                                Warning: If you change the -o parameter, sldl won't be able\n                                to index the downloaded files.\n                                Note that -x causes yt-dlp to download webms in case ffmpeg\n                                is unavailable.\n\n--search-timeout \u003cms\u003e           Max search time in ms (default: 6000)\n--max-stale-time \u003cms\u003e           Max download time without progress in ms (default: 30000)\n--searches-per-time \u003cnum\u003e       Max searches per time interval. Higher values may cause\n                                30-minute bans, see `--help search`. (default: 34)\n--searches-renew-time \u003csec\u003e     Controls how often available searches are replenished.\n                                See `--help search`. (default: 220)\n```\n#### Spotify Options\n```\n--spotify-id \u003cid\u003e               Spotify client ID\n--spotify-secret \u003csecret\u003e       Spotify client secret\n--spotify-token \u003ctoken\u003e         Spotify access token\n--spotify-refresh \u003ctoken\u003e       Spotify refresh token\n--remove-from-source            Remove downloaded tracks from source playlist\n```\n#### YouTube Options \n```\n--youtube-key \u003ckey\u003e             Youtube data API key\n--get-deleted                   Attempt to retrieve titles of deleted videos from wayback\n                                machine. Requires yt-dlp.\n--deleted-only                  Only retrieve \u0026 download deleted music.\n```\n#### CSV File Options\n```\n--artist-col \u003cname\u003e             Artist column name\n--title-col \u003cname\u003e              Track title column name\n--album-col \u003cname\u003e              Album column name\n--length-col \u003cname\u003e             Track length column name\n--album-track-count-col \u003cname\u003e  Album track count column name (sets --album-track-count)\n--yt-desc-col \u003cname\u003e            Youtube description column (improves --yt-parse)\n--yt-id-col \u003cname\u003e              Youtube video id column (improves --yt-parse)\n\n--time-format \u003cformat\u003e          Time format in Length column of the csv file (e.g h:m:s.ms\n                                for durations like 1:04:35.123). Default: s\n--yt-parse                      Enable if the CSV contains YouTube video titles and channel\n                                names; attempt to parse them into title and artist names.\n--remove-from-source            Remove downloaded tracks from source CSV file\n```\n#### File Condition Options\n```\n--format \u003cformats\u003e              Accepted file format(s), comma-separated, without periods\n--length-tol \u003csec\u003e              Length tolerance in seconds\n--min-bitrate \u003crate\u003e            Minimum file bitrate\n--max-bitrate \u003crate\u003e            Maximum file bitrate\n--min-samplerate \u003crate\u003e         Minimum file sample rate\n--max-samplerate \u003crate\u003e         Maximum file sample rate\n--min-bitdepth \u003cdepth\u003e          Minimum bit depth\n--max-bitdepth \u003cdepth\u003e          Maximum bit depth\n--strict-title                  File name must contain track title\n--strict-artist                 File path must contain artist name\n--strict-album                  File path must contain album name\n--banned-users \u003clist\u003e           Comma-separated list of users to ignore\n\n--pref-format \u003cformats\u003e         Preferred file format(s), comma-separated (default: mp3)\n--pref-length-tol \u003csec\u003e         Preferred length tolerance in seconds (default: 3)\n--pref-min-bitrate \u003crate\u003e       Preferred minimum bitrate (default: 200)\n--pref-max-bitrate \u003crate\u003e       Preferred maximum bitrate (default: 2500)\n--pref-min-samplerate \u003crate\u003e    Preferred minimum sample rate\n--pref-max-samplerate \u003crate\u003e    Preferred maximum sample rate (default: 48000)\n--pref-min-bitdepth \u003cdepth\u003e     Preferred minimum bit depth\n--pref-max-bitdepth \u003cdepth\u003e     Preferred maximum bit depth\n--pref-banned-users \u003clist\u003e      Comma-separated list of users to downrank\n\n--strict-conditions             Skip files with missing properties instead of accepting by\n                                default; if --min-bitrate is set, ignores any files with\n                                unknown bitrate. Warning: Available props depend on client\n```\n#### Album Download Options\n```\n-a, --album                     Album download mode: Download a folder\n-t, --interactive               Interactively select folders. See --help shortcuts.\n--album-track-count \u003cnum\u003e       Specify the exact number of tracks in the album. Add a + or\n                                - for inequalities, e.g '5+' for five or more tracks.\n--album-art \u003coption\u003e            Retrieve additional images after downloading the album:\n                                'default': No additional images\n                                'largest': Download from the folder with the largest image\n                                'most': Download from the folder containing the most images\n--album-art-only                Only download album art for the provided album\n--no-browse-folder              Do not automatically browse user shares to get all files in\n                                the folder\n--failed-album-path             Path to move all album files to when one of the items from\n                                the directory fails to download. Set to 'delete' to delete\n                                the files instead. Set to 'disable' keep them where they \n                                are. Default: {configured output dir}/failed\n--album-parallel-search         Run album searches in parallel, then download sequentially.\n--album-parallel-search-count   Number of parallel album searches (default: 5) \n```\n#### Aggregate Download Options\n```\n-g, --aggregate                 Aggregate download mode: Find and download all distinct\n                                songs associated with the provided artist, album, or title.\n--aggregate-length-tol \u003ctol\u003e    Max length tolerance in seconds to consider two tracks or\n                                albums equal. (Default: 3)\n--min-shares-aggregate \u003cnum\u003e    Minimum number of shares of a track or album for it to be\n                                downloaded in aggregate mode. (Default: 2)\n--relax-filtering               Slightly relax file filtering in aggregate mode to include\n                                more results\n```\n#### Printing \u0026 Debug Options\n```\n-v, --verbose                   Print extra debug info\n--log-file \u003cpath\u003e               Write debug info to a specified file\n--no-progress                   Disable progress bars/percentages, only simple printing\n--print \u003coption\u003e                Print tracks or search results instead of downloading:\n                                'tracks': Print all tracks to be downloaded\n                                'tracks-full': Print extended information about all tracks\n                                'results': Print search results satisfying file conditions\n                                'results-full': Print search results including full paths.\n                                'json': Print first result in json format\n                                'json-all': Print json of all results in sorted order\n                                'link': Print first result slsk:// link\n                                'index': Print sldl index as formatted json\n                                'index-failed': Print failed downloads from sldl index\n\n--mock-files-dir \u003cpath\u003e         Directory containing files to simulate download results\n--mock-files-no-read-tags       Only read filenames when simulating (much faster)\n```\n### Notes\n- Flags can be explicitly disabled by setting them to false, e.g. `--interactive false`.\n- Single-character flags can be combined, e.g. `-at` for `-a -t`.\n- Acronyms of two- and `--three-word-flags` like `--twf` are also accepted. E.g. `--Mbr` for `--max-bitrate`.\n\u003c!-- sldl-help:end --\u003e\n\n\u003c!-- sldl-help:start(input) --\u003e\n## Input types\nThe input type is usually determined automatically. You can also manually set it with `--input-type`.  \nThe following input types are available:\n\n###  CSV file\nPath to a local CSV file. Use a csv file containing track information to download a list of\nsongs or albums. Only the title or album column is required, but extra info may improve search\nresult ranking. If the columns have common names ('Artist', 'Title', 'Album', 'Length', etc)\nthen it's not required to manually specify them, otherwise you must provide at least `--title-col` or `--album-col`.   \nRows that do not have any text in the title column will be treated as album downloads.\n\n###  YouTube\nA YouTube playlist url. Download songs from a youtube playlist.  \n**Note:** The default method to retrieve playlists might not reliably return all videos. To get all\nvideos, you can use the official API by providing a key with `--youtube-key`. A key can\nbe obtained at https://console.cloud.google.com. Create a new project, click 'Enable Api' and\nsearch for 'youtube data', then follow the prompts.\n\n### Spotify\nAny playlist or album url, or `spotify-likes` for your liked songs, or `spotify-albums` for liked albums.  \nCredentials are required when downloading a private playlist or liked music.\n\n#### Using Credentials\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\nCreate a Spotify application at https://developer.spotify.com/dashboard/applications with a redirect url http://127.0.0.1:48721/callback. Obtain an application ID and secret from the created application dashboard.\n\nStart sldl with the obtained credentials and an authorized action to trigger the Spotify app login flow:\n\n```\nsldl spotify-likes --spotify-id 123456 --spotify-secret 123456 -n 1 --print-tracks\n```\nsldl will try to open a browser automatically but will fallback to logging the login flow URL to output. After login flow is complete sldl will output a token and refresh token and finish running the current command.\n\nTo skip requiring login flow every time sldl is used the token and refresh token can be provided to sldl (hint: store this info in the config file to make commands less verbose):\n\n```\nsldl spotify-likes --spotify-id 123456 --spotify-secret 123456 --spotify-refresh 123456 --spotify-token 123456 -n 1 --pt\n```\n\nspotify-token access is only valid for 1 hour. spotify-refresh will enable sldl to renew access every time it is run (and can be used without including spotify-token)\n\u003c/details\u003e\n\n### Bandcamp\nA bandcamp track, album, or artist url. Download a single track, an album, or an artist's\nentire discography. Also accepts wishlist URLs. Extraction might fail due to cloudflare; download the html to a local file and point sldl to it using `--from-html` in case of issues.\n\n### MusicBrainz\nA MusicBrainz.org URL for a release, release group, or collection.\n- A `/release/...` URL is treated as a single album download with a strict track count.\n- A `/release-group/...` URL is also treated as a single album download. It tries to pick the most common version of the album. Sets the minimum album track count to the chosen release track count, and no maximum track count unless `--extract-max-track-count` is set.\n- A `/collection/...` URL is treated as a list of albums, downloading each release contained within the collection.\n\n### Soulseek Link\nA direct path starting with `slsk://`. Paths ending in `/` will be treated as album downloads.\n\n### Search string\nName of the track, album, or artist to search for. The input can either be an arbitrary\nsearch string (like what you would type in the soulseek search bar), or a comma-separated\nlist of properties of the form `title=Song Name, artist=Artist Name, length=215`.\n\nThe following properties are accepted: title, artist, album, length (in seconds), \nartist-maybe-wrong, album-track-count.\n\nString input accepts a shorthand for track and album downloads: The input `ARTIST - TITLE`\nwill be parsed as `artist=ARTIST, title=TITLE` when downloading songs, and\n`artist=ARTIST, album=TITLE` when run with `--album`.\n\n### List file\nList input must be manually activated with `--input-type=list`. The input must be a path to a text\nfile containing lines of the following form:\n```ini\n# Any input type                conditions (optional)           pref. conditions (optional)\n\"Artist - Song\"                 \"format=mp3; br\u003e128\"            \"br \u003e= 320\"\n\n# Album download shorthand:\na:\"Artist - Album\"              format=flac\n# Add strict-* conditions depending on the name \na:\"Another Album\"               strict-album=true\n```\nThe inputs can be any of the above input types, including links. The conditions are added on top of the\nconfigured conditions and can be omitted. \n\u003c!-- sldl-help:end --\u003e\n\n\u003c!-- sldl-help:start(download-modes) --\u003e\n## Download modes\n### Normal\nThe default for playlists. Downloads a single file for every input entry.\n\n### Album\nsldl will search for the album and download an entire folder including non-audio\nfiles. Activated when the input is a link to a spotify or bandcamp album, when the input\nstring or csv row has no track title, or when `-a/--album` is enabled.\n\n### Aggregate\nWith `-g/--aggregate`, sldl performs an ordinary search for the input, then attempts to\ngroup the results into distinct songs and download one of each, starting with the one shared\nby the most users. Note that `--min-shares-aggregate` is 2 by default, meaning that songs\nshared by only one user will be ignored. Aggregate mode can be used to download all songs by \nan artist.  \n\n### Album Aggregate\nActivated when both `--album` and `--aggregate` are enabled. sldl will group shares and\ndownload one of each distinct album, starting with the one shared by the most users. Note\nthat `--min-shares-aggregate` is 2 by default, meaning that albums shared by only one user\nwill be ignored. Album-aggregate mode can be used to download the most popular (or all) albums\nby an artist. It is recommended to pair it with `--interactive`. See [Example](#download-all-albums-by-an-artist-interactively) for more details.\n\u003c!-- sldl-help:end --\u003e\n\n\u003c!-- sldl-help:start(config) --\u003e\n## Configuration\n### Config Location\nsldl will look for a file named sldl.conf in the following locations:\n\n- `~/AppData/Roaming/sldl/sldl.conf`\n- `~/.config/sldl/sldl.conf`\n- `$XDG_CONFIG_HOME/sldl/sldl.conf`\n- `{sldl executable dir}/sldl.conf`\n\n### Syntax\nExample config file:\n```ini\nusername = your-username\npassword = your-password\npref-format = flac\nfast-search = true\n```\nLines starting with hashtags # will be treated as comments. Tildes in paths are expanded as the user\ndirectory (even on windows). The path variable `{bindir}` stores the directory of the sldl binary.\n\n### Configuration profiles\nProfiles are supported:\n```ini\n[lossless]\npref-format = flac,wav\n```\nTo activate the above profile, run `--profile lossless`. To list all available profiles,\nrun `--profile help`.  \nProfiles can be activated automatically based on a few simple conditions:\n```ini\n# never automatically cancel album downloads in interactive mode\n[no-stale]\nprofile-cond = interactive \u0026\u0026 download-mode == \"album\"\nmax-stale-time = 9999999\n\n# download to another location for youtube\n[youtube]\nprofile-cond = input-type == \"youtube\"\npath = ~/downloads/sldl-youtube\n```\nThe following operators are supported for use in profile-cond: \u0026\u0026, ||, ==, !=, !{bool}.  \nThe following variables are available:\n```\ninput-type        (\"youtube\"|\"csv\"|\"string\"|\"bandcamp\"|\"spotify\")\ndownload-mode     (\"normal\"|\"aggregate\"|\"album\"|\"album-aggregate\")\ninteractive       (bool)\n```\n\u003c!-- sldl-help:end --\u003e\n\n\u003c!-- sldl-help:start(file-conditions) --\u003e\n## File conditions\nFiles not satisfying the required conditions will be ignored. Files satisfying pref-conditions\nwill be preferred: With `--pref-format flac,wav`, sldl will try to download lossless files if\navailable while still accepting lossy files.\n\nThere are no default required conditions. The default preferred conditions are:\n```ini\npref-format = mp3\npref-length-tol = 3\npref-min-bitrate = 200\npref-max-bitrate = 2500\npref-max-samplerate = 48000\npref-strict-title = true\npref-strict-album = true\n```\nsldl will therefore prefer mp3 files with bitrate between 200 and 2500 kbps, and whose length\ndiffers from the supplied length by no more than 3 seconds. Moreover, it will prefer files\nwhose paths contain the supplied title and album. Changing the last two preferred conditions is\nnot recommended.  \n\nNote that files satisfying only a subset of the conditions will be preferred over files that don't\nsatisfy any condition. Run a search with `--print results-full` to reveal the sorting logic.\n\nConditions can also be supplied as a semicolon-delimited string with `--cond` and `--pref`, e.g\n`--cond \"br\u003e=320; format=mp3,ogg; sr\u003c96000\"`.\n\n### Note on availability of metadata\nSome info may be unavailable depending on the client used by the peer. If (e.g) `--min-bitrate`\nis set, then sldl will still accept any file with unknown bitrate. To reject all files where one\nor more of the checked properties is null (unknown), enable `--strict-conditions`.  \n\nThis flag should be used with care: It's easy to accidentally exclude all files from users with\ncertain clients. For example, because the standard Soulseek client does not broadcast the bitrate,\nenabling `--strict-conditions` and setting a `--min-bitrate` will make sldl ignore all files\nshared by users with the standard client. Even without a required min-bitrate, all those shares\nwill be ranked at the bottom due to the default pref- bitrate checks.\n\u003c!-- sldl-help:end --\u003e\n\n\u003c!-- sldl-help:start(name-format) --\u003e\n## Name format\nVariables enclosed in {} will be replaced by the corresponding file tag value.\nName format supports subdirectories as well as conditional expressions like {tag1|tag2} - If\ntag1 is null, use tag2. This can be chained arbitrarily many times. String literals enclosed\nin parentheses are ignored in the null check.\n\n### Examples\n- `{artist} - {title}`  \n    Always name it 'Artist - Title'. Because some files on Soulseek are untagged, the\n    following is generally preferred:\n- `{artist( - )title|filename}`  \n    If artist and title are not null, name it 'Artist - Title', otherwise use the original\n    filename.\n- `{albumartist(/)album(/)track(. )title|(missing-tags/)slsk-foldername(/)slsk-filename}`  \n    Sort files into artist/album folders if all tags are present, otherwise put them in\n    the 'missing-tags' folder.   \n\n### Available variables\n\nThe following values are read from the downloaded file's tags:\n```\nartist                         First artist\nartists                        Artists, joined with '\u0026'\nalbumartist                    First album artist\nalbumartists                   Album artists, joined with '\u0026'\ntitle                          Track title\nalbum                          Album name\nyear                           Track year\ntrack                          Track number\ndisc                           Disc number\nlength                         Track length (in seconds)\n```\n\nThe following values are taken from the input source (CSV file data, Spotify, etc):\n```\nsartist                        Source artist\nstitle                         Source track title\nsalbum                         Source album name\nslength                        Source track length\nuri                            Track URI\nsnum                           Source item number (1-indexed, including offset)\nrow/line                       Line number (1-indexed, only for CSV or list input)\n```\n\nOther variables:\n```\ntype                           Track type\nstate                          Track state\nfailure-reason                 Reason for failure if any\nis-audio                       If track is audio (true/false)\nartist-maybe-wrong             If artist might be incorrect (true/false)\nslsk-filename                  Soulseek filename without extension\nslsk-foldername                Soulseek folder name\nextractor                      Name of the extractor used\ninput                          Input string\nitem-name                      Name of the playlist/source\ndefault-folder                 Default sldl folder name\nbindir                         Base application directory\npath                           Download file path (or folder if album)\npath-noext                     Download file path without extension\next                            File extension\n```\n\u003c!-- sldl-help:end --\u003e\n\n\u003c!-- sldl-help:start(on-complete) --\u003e\n## On-Complete Actions\nThe `--on-complete` parameter allows executing commands after a track or album is downloaded. Multiple actions can be chained using the `+ ` prefix (note the space after +).\n\n**Syntax:** `--on-complete [prefixes:]command`\n\nHint: You can use `--mock-files-dir` to test your commands (see [Testing Options](#testing-options)).\n\n### Prefixes\n- `1:` - Execute only if track downloaded successfully\n- `2:` - Execute only if track failed to download\n- `a:` - Execute only after album download\n- `s:` - Use shell execute\n- `h:` - Hide window\n- `r:` - Read command output\n- `u:` - Use output to update index (implies `r:`)\n\nWhen using u: prefix, the command output should be `new_state;new_path` to update the track state and path in the index and playlist.\n\n### Variables\n\nThe available variables are the same as in name-format, with the following additions:\n- `{exitcode}` - Previous command's exit code\n- `{stdout}` - Previous command's stdout (requires r:)\n- `{stderr}` - Previous command's stderr (requires r:)\n- `{first-exitcode}` - First command's exit code\n- `{first-stdout}` - First command's stdout (requires r:)\n- `{first-stderr}` - First command's stderr (requires r:)\n\n### Examples\n\nThe following examples are for Windows, but can be easily adapted for any OS.  \n  \nSearch album art with [Cover Fetcher](https://github.com/fiso64/cover-fetcher):\n```ini\non-complete = 1:h:a: cmd /c start \"\" \"path\\to\\CoverFetcher.exe\" --from-dir \"{path}\"\n```\n\nQueue downloaded audio files in foobar2000:\n```ini\non-complete = 1:h: cmd /c if {is-audio}==true start \"\" \"path\\to\\foobar2000.exe\" /immediate /add \"{path}\"\n```\n\nConvert downloaded audio files to MP3 (requires ffmpeg):\n```ini\n# Check if file is audio and not already MP3\non-complete =   1:h:r: cmd /c if {is-audio}==true if /i not {ext}==.mp3 if not exist \"{path-noext}.mp3\" echo true\n\n# Convert to MP3 if check passed\non-complete = + 1:h:r: cmd /c if {stdout}==true (ffmpeg -i \"{path}\" -q:a 0 \"{path-noext}.mp3\" \u0026\u0026 echo success)\n\n# Delete original and update index if conversion succeeded\non-complete = + 1:h:u: cmd /c if {stdout}==success (del \"{path}\" \u0026 echo \"1;{path-noext}.mp3\")\n```\n\u003c!-- sldl-help:end --\u003e\n\n\u003c!-- sldl-help:start(shortcuts) --\u003e\n## Shortcuts \u0026 interactive mode\n### Shortcuts\nTo cancel a running album download, press `C`.\n\n### Interactive mode\nInteractive mode for albums can be enabled with `-t`/`--interactive`. It enables users to choose the desired folder or download specific files from it.\n\nKey bindings:\n```\nUp/p            previous folder\nDown/n          next folder\nEnter/d         download selected folder\ny               download folder and disable interactive mode\nr               retrieve all files in the folder\ns               skip current item\nEsc/q           quit program\nh               print this help text\n\nd:1,2,3         download specific files\nd:start-end     download a range of files\nf:query         filter folders containing files matching query\ncd ..           load parent folder\ncd subdir       go to subfolder\n```\n\u003c!-- sldl-help:end --\u003e\n\n## Examples\n\n##### Download tracks from a csv file\n```bash\nsldl \"tracks.csv\"\n```\n\n##### Download a Spotify playlist or your liked songs\n```bash\nsldl \"https://open.spotify.com/playlist/id\"\nsldl \"spotify-likes\"\n```\n\n##### Download the albums of a spotify playlist\n```bash\nsldl \"https://open.spotify.com/playlist/id\" -a\n```\n\n##### Download a youtube playlist with yt-dlp fallback \u0026 retrieving deleted video names\n```bash\nsldl \"https://youtube.com/playlist/id\" --get-deleted --yt-dlp\n```\n\n##### Interactive album download, only include albums with 13 or more tracks\n```bash\nsldl \"Album Name\" -at --atc 13+\n```\n\n##### Download a specific song by name and length, preferring lossless\n```bash\nsldl \"MC MENTAL @ HIS BEST, length=242\" --pref-format \"flac,wav\"\n``` \n\n##### Download all albums by an artist interactively\n```bash\nsldl \"artist=MC MENTAL\" -agt\n```\nThis command will show an interactive UI listing all albums with appearances by the specified artist, starting with the most popular (based on the number of shares). You can download or skip albums as needed. sldl will do its best to group shares of the same album into a single entry (but due to differences in filenames this will not be 100% reliable). For some artists, it can be useful to add `--strict-artist` to avoid listing incorrect results. There is currently no way to only include albums *by that artist*, rather than every album/compilation where that artist appeared (feel free to request it if needed).\n\n##### Print all songs by an artist which are not in your library\n```bash\nsldl \"artist=MC MENTAL\" -g --skip-music-dir \"path/to/music\" --print results\n```\n\n### Advanced example: Automatic wishlist downloader\nCreate a file named `wishlist.txt`, and add some items as detailed in [Input types: List](#list-file):\n```\n\"Artist - My Favorite Song\"            format=flac\na:\"Artist - Some Album\"                strict-album=true;album-track-count=5\n```\nAdd a profile to your `sldl.conf`:\n```ini\n[wishlist]\ninput = ~/sldl/wishlist.txt \ninput-type = list\nindex-path = ~/sldl/wishlist-index.sldl\nalbum-parallel-search = true\n```\nThis will create a global index file `wishlist-index.sldl` which will be scanned every time sldl is run to skip wishlist items that have already been downloaded. If you want to continue searching until a version satisfying the preferred conditions is found, also add `skip-check-pref-cond = true` (note that this requires the files to remain in the same spot after being downloaded).  \n\nNow you can manually run, or set up a cron job / scheduled task to periodically run sldl with the following option:\n```bash\nsldl --profile wishlist\n```\n\n\u003c!-- sldl-help:start(notes-and-tips) --\u003e\n## Notes\n- **Terminal display issues**: The printed output may appear duplicated, overlap, or not update on some configurations (new windows terminal, git bash). Use another terminal or `--no-progress` in case of issues. See https://github.com/fiso64/slsk-batchdl/issues/55.\n- **Soulseek's rate limits**: The server bans users for 30 minutes if too many searches are performed within a short timespan. sldl has a search limiter which can be adjusted with `--searches-per-time` and `--searches-renew-time` (when the limit is reached, the status of the downloads will be 'Waiting'). By default it is configured to allow up to 34 searches every 220 seconds.\n\n## Tips\n\n### Searching\n\n- It's always best to provide the least input necessary to uniquely identify an album or song.\n  - Sometimes including the artist can be undesirable (e.g. \"Various Artists\"). For spotify or bandcamp inputs, you can remove the artist name with `--regex A:.*`.\n  - Use `--remove-ft` to remove \"feat.\" or \"ft.\" artists \n- You can download an entire album based on the name of one of its songs by searching for that name with `-a/--album`. \n- When searching for a single song with a string input, you can provide the album name in addition. The album name will not be included in the query, but search results containing it will be preferred (due to pref-strict-album).\n- When dealing with YouTube playlists you may want to remove any text in parentheses (like (Video)), as well as \"Official\" and \"Lyrics\" with `--regex \"[\\[\\(].*?[\\]\\)]|(?i:lyrics)|(?i:official)\"` \n\n### Filtering Irrelevant Results\n\nsldl typically selects the correct files as long as they appear in the search results. By default, it always tries to download something and does no additional filtering. However, you can use the following options to filter your search results:\n\n- `--strict-title`, `--strict-artist`, `--strict-album`  \n  Filters out files whose paths do not include the specified title, artist, or album name (ignoring case and using boundary characters). Because the pref- versions of these options are enabled by default, they are only recommended when you want to reduce false downloads, e.g. for [wishlists](#advanced-example-automatic-wishlist-downloader) where there is a high probability that the item does not exist on the network.\n\n- `--length-tol`  \n  For normal downloads, this option sets a tolerance level by which the file’s length can differ from the input length. The default preference (--pref-length-tol) is set to 3 seconds.\n\n- `--album-track-count`  \n  When downloading an album, you can specify this option to ensure the album contains a certain number of tracks. For instance, if the input is a Spotify or Bandcamp album, this field is automatically set to `n+` (where n is the number of tracks on the album). This ensures that only albums with at least n tracks are accepted (useful when there are more complete versions of the album on soulseek).\n\n\n### Speeding things up\nThe following options will make it go faster, but may decrease search result quality or cause instability:\n\n- `--fast-search` skips waiting until the search completes and downloads as soon as a file matching the preferred conditions is found\n- `--concurrent-downloads` can be set it to 4 or more. This only affects normal downloads (not album).\n- `--max-stale-time` is set to 30 seconds by default, sldl will wait a long time before giving up on a file.\n- `--album-parallel-search` enables parallel searching for album entries\n\n### Testing Options\nYou can test almost any aspect of the search and downloading logic by using `--mock-files-dir` and pointing it to a local directory containing audio files. This directory will then be used instead of searching Soulseek. Example:\n```\nsldl \"Artist - Album\" -at --mock-files-dir /path/to/dir\n```\nIf you plan to use a large music library, you may want to add `--mock-files-no-read-tags` to improve the initial loading performance. But note that reading tags is required when filtering by metadata such as length or bitrate.\n\n\u003c!-- sldl-help:end --\u003e\n\n## Docker\n\nA docker container for running `sldl` can be built from this repository. The image supports linux x86/ARM. \n\nTo build and start container:\n\n```shell\nclone https://github.com/fiso64/slsk-batchdl\ncd slsk-batchdl\ndocker compose up -d\n```\n\n`exec` into the container to start using `sldl`:\n\n```shell\ndocker compose exec sldl sh\nsldl --help\n```\n\nThe compose stack mounts two directories relative to where `docker-compose.yml` is located which can be used for file management:\n\n* `/config` (at `./config` on host) - put your `sldl.conf` [configuration](#configuration-) in this directory and then use `sldl -c /config ...` to use your configuration in the container\n* `/data` (at `./data` on host) - use as the download directory IE `sldl -p /data ...`\n\n### File Permissions\n\nIf you are running Docker on a **Linux Host** you should specify `user:group` permissions of the user who owns the **configuration and data directory** on the host to avoid [docker file permission problems.](https://ikriv.com/blog/?p=4698) These can be specified using the [environmental variables **PUID** and **PGID**.](https://docs.linuxserver.io/general/understanding-puid-and-pgid)\n\nTo get the UID and GID for the current user run these commands from a terminal:\n\n* `id -u` -- prints UID\n* `id -g` -- prints GID\n\nReplace these with the corresponding variable (`PUID` `PGID`) in `docker-compose.yml`.\n\n\n### Cron\n\nOne or more `sldl` commands can be run on a schedule using [cron](https://en.wikipedia.org/wiki/Cron) built into the container.\n\nTo create a schedule make a new file on the host `./config/crontabs/abc` and use it with the standard [crontab](https://en.wikipedia.org/wiki/Cron#Overview) syntax.\n\nMake sure to restart the container after any changes to the cron file are made.\n\nExample =\u003e Run `sldl` every Sunday at 1am, search for missing tracks from the specified Spotify playlist\n\n```\n# min   hour    day     month   weekday command\n0 1 * * 0 sldl https://open.spotify.com/playlist/6sf1WR5grXGJ6dET -c /config -p /data --index-path /data/index.sldl\n```\n\n[crontab.guru](https://crontab.guru/) could be used to help with the scheduling expression.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffiso64%2Fsldl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffiso64%2Fsldl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffiso64%2Fsldl/lists"}