Go back to the hardlink deduplicator (1da0132), keeping backups
Restores the code of 1da0132 ("Add a setting to hide the quarantine from
Plex") and removes everything added after it: the tag editor, album art,
organizing/naming, the step-by-step tune-up and library types.
Kept:
- Database backups (Settings -> Backups): scheduled, manual, download,
restore, and the optional backup before every action.
- The .env-driven docker-compose.yml for Arcane.
Databases that already ran the later migrations keep working: migrations
6-10 stay in the list (they only add columns) so numbering never goes
backwards, and Undo refuses History entries of removed features instead
of treating them as links.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7b180e26db
commit
e0617047f7
44 files changed
+103
-10456
No files matched your search
@@ -7,32 +7,6 @@ up disk space only once, while both libraries keep looking exactly the same to P
|
||||
It ships as a single Go binary with an embedded React web UI and SQLite state, packaged as a small Docker image, in the style of
|
||||
[qui](https://github.com/autobrr/qui).
|
||||
|
||||
## Workflow: tune up, then link
|
||||
|
||||
Each library pair has a **type**: **Music** (recommended layout `Artist/Album/01 Title.flac`) or **Soundtracks** for video game and film
|
||||
soundtracks (`Album/01 Title.flac`, named by game or film). The type sets the default naming; the *Organize* tab can change it.
|
||||
|
||||
The **Tune-up** tab takes each library through the same steps, the **master first, then the slave**, and then links the two:
|
||||
|
||||
1. **Folder structure.** Every album in its own folder at the right depth. Songs outside an album folder move into one named from their
|
||||
tags; extra folders around an album (a composer folder around a soundtrack, `Metal/Artist/Album`, a `FLAC` folder inside an album) are
|
||||
removed; songs in disc folders (`CD2`, `Disc 2`) get their disc number; missing titles, track numbers, albums and artists are filled in
|
||||
from the folder and file names (`Album (2010) [FLAC]` → `Album`). When several albums sit in the same extra folder it may be a category
|
||||
you want to keep (`Video Games/…`), so those moves are listed but not selected, with a hint to give that folder its own naming.
|
||||
2. **Album tags** (optional). Each album is looked up on MusicBrainz: the best few releases are compared with your songs' titles (so a promo
|
||||
single never beats the album it is named after), songs are matched to tracks by number or title, and the corrected titles, track and
|
||||
disc numbers, album artist and date are shown per album for review, with a confidence rating. You can pick another release or edit the
|
||||
album by hand. In the slave, albums that are also in the (fixed) master take the master's tags instead, so both libraries match.
|
||||
MusicBrainz allows about one request a second, so large libraries take a while; limit it to a folder or skip albums whose tags are already
|
||||
complete.
|
||||
3. **Folder names.** Artist and album folders are renamed from the tags. Whole album folders move, so covers and booklets stay with them.
|
||||
4. **File names.** Songs are renamed from the tags; multi-disc albums get `Disc 01`, `Disc 02` folders.
|
||||
5. **Link the libraries.** Scan, fix any folders still named differently, link the identical songs, then open **Review** for the rest.
|
||||
|
||||
Every step is a check first: nothing changes until you apply the fixes you selected, each fix is an operation in History that can be undone,
|
||||
and dry run applies. Problems that need a person (a song without an album tag, a folder with songs from several albums) are listed with an
|
||||
**Edit album** button. A step is marked done when everything in it was fixed; you can also mark it done or skip it yourself.
|
||||
|
||||
## What it does
|
||||
|
||||
Files are matched by their **path relative to each library root**. Any folder layout works (`Artist/Album/Title.ext`,
|
||||
@@ -97,59 +71,10 @@ anything runs, a preview shows how many songs will be processed and which are sk
|
||||
downgrades, approximate matches, duration mismatches and files that move folders. Downgrades are skipped unless you tick a box, and
|
||||
replacing master files needs an explicit acknowledgement. Each song then goes through the same checks as a single action.
|
||||
|
||||
**Tag editor.** The *Tags* tab browses either library. Click a song to edit its tags (title, artist, album artist, album, track and
|
||||
disc numbers with totals, year, genre, composer, comment), or tick several, such as a whole album, to edit the tags they share. It
|
||||
works for MP3, FLAC, M4A, OGG and Opus; other tags and cover art are kept. Review's compare panel also has **Slave tags** / **Master
|
||||
tags** buttons. Edits are safe with hardlinks:
|
||||
|
||||
- A file used by only one library is rewritten to a new file that atomically replaces it; the old file goes to quarantine.
|
||||
- A file hardlinked to the other library is updated in place, so both libraries see the new tags and stay linked; a verified backup
|
||||
copy goes to quarantine first. You can instead choose to change only one library's copy, which breaks the link.
|
||||
- Every written file is verified: the new values must read back, and the decoded audio must be identical to the original.
|
||||
- Each edit is listed in History (old → new values) and can be undone; an in-place edit interrupted by a crash is rolled back on
|
||||
startup. Dry run applies.
|
||||
|
||||
**Album editor.** Every folder in *Tags* has an **Edit album** button (like AudioShell's folder view). It shows the album fields
|
||||
once (album, album artist, year, genre, discs, composer, comment); a change there updates every song in the album, including songs in
|
||||
`Disc 01`/`Disc 02` subfolders. Below is a track grid to edit each song's disc, track number, title and artist, with **Number tracks
|
||||
in order** (fills track and disc totals too) and **Artist = album artist**. All songs are saved as one job with the same safety
|
||||
checks as above.
|
||||
|
||||
**Album art.** The song and album editors can swap the cover. Search iTunes, Deezer, MusicBrainz (Cover Art Archive), DuckDuckGo
|
||||
or Google by artist and album or by free text; only square images are shown, and results under a minimum size are hidden. You can
|
||||
also paste an image address or upload a file. The chosen image is converted to JPEG at the saved size (1000 × 1000 by default) and
|
||||
can be embedded in the songs, saved as `cover.jpg` in the album folder, or both. OGG and Opus can't hold embedded art here, so they
|
||||
use the folder image. A replaced `cover.jpg` goes to quarantine, and every change can be undone from History.
|
||||
|
||||
- **Auto-match art…** walks the current folder, looks up each album on iTunes, Deezer and MusicBrainz, and applies a cover only when
|
||||
the artist and album clearly match (release suffixes like "Deluxe Edition" are ignored). Albums that already have art can be
|
||||
skipped; albums without a confident match are listed and left untouched.
|
||||
- Sources are chosen in *Settings → Album art*. Google needs an API key with the Custom Search API and a Programmable Search Engine
|
||||
id (cx). DuckDuckGo has no official API and may stop working. Images are downloaded by playlink itself and never from addresses on
|
||||
your local network.
|
||||
|
||||
**Organize (rename files from tags).** The *Organize* tab sets how files are named, in the style of Lidarr: an **artist folder**, an
|
||||
**album folder**, a **track format** and a separate **multi-disc track format**, with presets. The default is
|
||||
`{Artist Name}/{Album Title}/{track:00} {Track Title}`, and multi-disc albums get `{Medium Format} {medium:00}/…` → `Disc 01`, `Disc 02`.
|
||||
Leave the artist folder empty for `Album/01 Title`; songs then don't need an artist tag.
|
||||
|
||||
**Folders with their own naming.** Part of a library can use different formats, such as game soundtracks in
|
||||
`Video Games/{Album Title}/{track:00} {Track Title}` while the rest stays `Artist/Album/01 Title`. Files inside such a folder are only
|
||||
renamed within it, and other files are never moved into it (they are skipped with a reason instead). Folder rules can't be nested.
|
||||
|
||||
Tokens: `{Artist Name}`, `{Artist NameThe}` (The Beatles → Beatles, The), `{Artist CleanName}`, `{Artist NameFirstCharacter}`,
|
||||
`{Album Title}`, `{Album TitleThe}`, `{Album CleanTitle}`, `{Release Year}`, `{track:0}`/`{track:00}`, `{medium:0}`/`{medium:00}`,
|
||||
`{Medium Format}`, `{Track Title}`, `{Track CleanTitle}`, `{Track ArtistName}`, `{Genre}`. Like Lidarr, `{Artist.Name}` or `{Artist_Name}`
|
||||
puts dots or underscores between words and `{ARTIST NAME}` / `{artist name}` change the case. The artist is the album artist, falling back
|
||||
to the artist. Colons can be replaced smartly (`A: B` → `A - B`), with a dash, space dash, space dash space, or deleted; other characters
|
||||
Windows/SMB rejects are replaced (`AC/DC` → `AC-DC`) or removed. Brackets and separators left empty by a missing value are cleaned up
|
||||
(`Album ({Release Year})` without a year → `Album`). Examples are rendered by the same code that renames files.
|
||||
|
||||
**Rename now…** checks the slave, the master or both, then shows every change grouped by destination folder (old → new, selectable per
|
||||
file or folder), plus skipped files with the reason and a *Fix tags* button. Files are only moved within their library, so contents and
|
||||
hardlinks never change; lyrics (`.lrc`) move with their song, cover art follows a whole folder, and emptied folders are removed. Each
|
||||
rename is in History and can be undone, and the library is rescanned afterwards. **Organize automatically** (off by default) applies the
|
||||
same renames during every scan. A slave file that is a hardlink of a master file at a different path is still recognised as linked.
|
||||
**Export.** The Review tab's **Export CSV** button downloads either the current view (filter and search applied) or the entire scan.
|
||||
Each row has the match status and type, a recommendation, both paths, where linking would place the file, codec, bitrate, sample rate,
|
||||
bit depth and duration for both sides, the quality verdict and any notes. The file opens cleanly in Excel, Numbers and LibreOffice
|
||||
(UTF-8, and cells a spreadsheet would treat as formulas are escaped).
|
||||
|
||||
**Backups** (Settings → Backups), similar to Sonarr. A backup is a zip of playlink's database (settings, library pairs, scan results and
|
||||
history, not music files) taken safely while the app runs. Choose a folder (default `/config/backups`), a schedule (off, every 1, 3, 7
|
||||
@@ -159,11 +84,6 @@ are refused), then playlink restarts to swap the database in and keeps the repla
|
||||
policy brings it back automatically. Optionally, **back up before every action in live mode**: one backup per action you start (and
|
||||
before scans change files), never one per file; if that backup fails the action does not run, and the newest 10 are kept.
|
||||
|
||||
**Export.** The Review tab's **Export CSV** button downloads either the current view (filter and search applied) or the entire scan.
|
||||
Each row has the match status and type, a recommendation, both paths, where linking would place the file, codec, bitrate, sample rate,
|
||||
bit depth and duration for both sides, the quality verdict and any notes. The file opens cleanly in Excel, Numbers and LibreOffice
|
||||
(UTF-8, and cells a spreadsheet would treat as formulas are escaped).
|
||||
|
||||
**Build mode** covers the "start fresh" workflow. Point the slave at an empty folder, browse the master library, tick the
|
||||
folders or songs you want, and playlink hardlinks them in at the same relative path. **Remove** deletes slave files, but only ones that are hardlinks of the
|
||||
master file.
|
||||
@@ -245,8 +165,7 @@ Run a scan, check the Review tab, and turn off dry run once the planned actions
|
||||
| `PLAYLINK_DATA_DIR` | `/config` (Docker) or `./config` | Where the SQLite database lives. |
|
||||
| `PLAYLINK_ALLOWED_ROOTS` | `/data` | Comma-separated folders that libraries and the quarantine must live in. `/` is refused. |
|
||||
| `PLAYLINK_SECURE_COOKIES` | `false` | Set to `true` when served over HTTPS. |
|
||||
| `PLAYLINK_FFPROBE` | `ffprobe` | Path to ffprobe. Without it, quality comparison and tag editing are disabled. |
|
||||
| `PLAYLINK_FFMPEG` | `ffmpeg` | Path to ffmpeg, used by the tag editor. |
|
||||
| `PLAYLINK_FFPROBE` | `ffprobe` | Path to ffprobe. Without it, quality comparison is disabled but everything else works. |
|
||||
| `PLAYLINK_LOG_LEVEL` | `info` | `debug` for verbose logs. |
|
||||
|
||||
**Hide quarantine from Plex** (Settings → Media servers) writes a `.plexignore` into each pair's quarantine folder so Plex does not
|
||||
|
||||
Reference in new issue
Block a user