The array root carried 48 planning artifacts (journals, plans, run logs) accumulated by the relayout campaigns since 2026-11-02. They sit beside the libraries now, which is how a media server ends up indexing a journal. Moved all 48 (219.8 MiB) into the dot-directory `/mnt/entropy/.media-campaign` with a journaled `media-apply` run (plan, apply, verify — 48 verified at their targets, 0 root files left). Jellyfin and Plex ignore dot-directories, and the overlay view exposes the array root to both servers, so the same pollution existed on the view side. Every vault page that named a root-level journal path is rewritten to the new home (26 occurrences across 6 pages), and the law is stated once, in [[Media Relayout]], which owns the tool chain: `media-apply.py` defaults its journal to `media-relayout.jsonl` beside `--root`, so a run that omits `--journal` recreates exactly the root-level log this now forbids.
69 lines
3.2 KiB
Markdown
69 lines
3.2 KiB
Markdown
---
|
|
type: reference
|
|
title: Media Music Relayout
|
|
description: "Re-filing /mnt/entropy/Music by Jellyfin's tag rows: the census, the album key, the refusals."
|
|
tags: [dankserver, media-server, jellyfin, media-relayout]
|
|
timestamp: 2026-10-31T00:00:00Z
|
|
---
|
|
|
|
# Media Music Relayout
|
|
|
|
`/mnt/entropy/Music` is rips and discography packs, and Jellyfin has matched and
|
|
tagged almost all of it. `scripts/media-music.py` re-files it into the shape
|
|
Jellyfin's music scanner reads —
|
|
|
|
Music/<album artist>/<Album> (<year>)/NN - <Title>.ext
|
|
|
|
— and the authority is the tag row of the track, never the name the ripper gave
|
|
the file. The shared gates, the executor, the journal law and the rollback live in
|
|
[[Media Relayout]]; this page is the music arm only.
|
|
|
|
```bash
|
|
# 1. The authority: Jellyfin's audio rows, one per track, with the album and
|
|
# artist ids its own database carries (the DB opens read-only).
|
|
python3 scripts/media-census.py music --root /mnt/entropy/Music \
|
|
--out /tmp/music_rows.tsv
|
|
# 2. What is on disk (stat only).
|
|
python3 scripts/media-census.py enumerate --root /mnt/entropy/Music \
|
|
--out /tmp/music_enum.tsv
|
|
# 3. The plan.
|
|
python3 scripts/media-music.py --root /mnt/entropy/Music --enum /tmp/music_enum.tsv \
|
|
--rows /tmp/music_rows.tsv --out /tmp/music_plan.tsv \
|
|
--exceptions /tmp/music_exceptions.txt
|
|
# 4. Read the exceptions file FIRST — it is the review, not a log. Then the same
|
|
# executor, journal and rollback as [[Media Relayout]] shows, on its own journal.
|
|
scripts/media-apply.py apply --plan /tmp/music_plan.tsv --root /mnt/entropy \
|
|
--journal /mnt/entropy/.media-campaign/media-relayout-music.jsonl --apply
|
|
```
|
|
|
|
The group is what the tags assert, not where the files sit: **(album-artist tag,
|
|
album, year)**. One album arrives as three disc folders and as two copies of one
|
|
rip, and one MusicBrainz release group is one album. A compilation is one album
|
|
whose tracks name many performers, so it files once under `Various Artists`:
|
|
keying on the performer would file one album once per artist. Two different
|
|
album-artist tags on one album name are two albums, which is what Jellyfin's two
|
|
album items say.
|
|
|
|
What it refuses:
|
|
|
|
+- **A sidecar is placed by the audio around it, never by its own name.** A
|
|
`.lrc`, `.txt` or picture that shares a track's stem follows that track and
|
|
takes the name the track now has, or Jellyfin cannot find it; anything else
|
|
goes to the album its own folder was placed in, or to the folder whose discs
|
|
sit one level below it. A folder whose audio belongs to two albums parks its
|
|
sidecar rather than guessing.
|
|
+- **An image album keeps its name.** A folder holding one audio file and a
|
|
`.cue` is a whole album in one file; numbering it `01 - …` tells Jellyfin to
|
|
index it as one track.
|
|
+- **A video container parks**, because Jellyfin will not index it as music and a
|
|
rename to `.m4a` would claim it is; **audio no provider row names parks** too,
|
|
because unmatched audio is a tagging job, not a renaming job.
|
|
|
|
ONE writer at a time on this array: two rename passes race, and neither journal
|
|
tells. Verify the run against Jellyfin's own tables — see *Proving the move
|
|
landed* in [[Media Relayout]].
|
|
|
|
## See Also
|
|
|
|
[[Media Relayout]], [[Jellyfin]], [[Media Audiobook Relayout]]
|