A track's tags are split where upstream does not split them #27

Closed
opened 2026-08-02 18:22:10 +02:00 by Claude · 1 comment
Collaborator

Upstream does not read a track's tags through the ffprobe normalizer. AudioFileProber
reads them with ATL and splits on ATL's own separator — one tag frame per value —
applying further delimiters only when a library sets UseCustomTagDelimiters, which
is off by default (AudioFileProber.cs:414-425, and the same shape for artists at
:378).

Ours runs every track through probe::tags, whose genre delimiters are / ; , and
whose artist handling replaces feat. before splitting. On the real library:

column tracks differing
Genres 1403 of 4889
Artists 13 of 4889
upstream Genres  'Ambient;Downtempo;Electronic'      one genre
ours     Genres  'Ambient|Downtempo|Electronic'      three

upstream Artists 'Aes Dana feat. MikTek'             one artist
ours     Artists 'Aes Dana|MikTek'                   two

The delimiter tables themselves match upstream's ProbeResultNormalizer exactly —
_basicDelimiters, _nameDelimiters, _genreDelimiters and the split whitelist are
all faithful. The divergence is that a track never reaches that code upstream.

Found while verifying #9: the by-name values a track is listed under are a faithful
reflection of these columns, so 46 of 429 ItemValues rows differ for this reason
alone — Acid Techno;Electronic;Idm;Techno is one genre upstream and four here.

Upstream does not read a track's tags through the ffprobe normalizer. `AudioFileProber` reads them with ATL and splits on ATL's own separator — one tag frame per value — applying further delimiters only when a library sets `UseCustomTagDelimiters`, which is off by default (`AudioFileProber.cs:414-425`, and the same shape for artists at `:378`). Ours runs every track through `probe::tags`, whose genre delimiters are `/ ; ,` and whose artist handling replaces `feat.` before splitting. On the real library: | column | tracks differing | |---|---| | `Genres` | 1403 of 4889 | | `Artists` | 13 of 4889 | upstream Genres 'Ambient;Downtempo;Electronic' one genre ours Genres 'Ambient|Downtempo|Electronic' three upstream Artists 'Aes Dana feat. MikTek' one artist ours Artists 'Aes Dana|MikTek' two The delimiter tables themselves match upstream's `ProbeResultNormalizer` exactly — `_basicDelimiters`, `_nameDelimiters`, `_genreDelimiters` and the split whitelist are all faithful. The divergence is that a track never reaches that code upstream. Found while verifying #9: the by-name values a track is listed under are a faithful reflection of these columns, so 46 of 429 `ItemValues` rows differ for this reason alone — `Acid Techno;Electronic;Idm;Techno` is one genre upstream and four here.
Author
Collaborator

Fixed in the merge of fix/27-tag-splitting.

The rule could not be fixed as a rule

The premise held — upstream reads a track with a tag library and splits only on
that library's own separator — but no delimiter table could reproduce it,
because ffprobe cannot say how many values a tag holds. Two files from this
library, one whose genres upstream splits and one whose it does not:

A Silver Mt. Zion … .flac    GENRE = 'Experimental;Post-Rock;Rock'
AES Dana … .mp3              genre = 'Ambient;Downtempo;Electronic'

Identical to the prober. Upstream tells them apart because ATL reads the file:
three Vorbis fields against one ID3 frame. Nor does the container predict it —
of the FLACs upstream split 1317 and left 1302 whole.

So the track is read twice

As upstream reads one. The prober answers what is in the container; the file's
own tags answer how many values a tag holds, and land in MediaInfo::written,
a value per frame. A track's artists, album artists, genres and composers are
read from there, and from what the prober made of the tag where no reader could
open the file. A video is untouched: upstream reads one through the normalizer
and never through a tag library, which is what the probe corpus records.

The columns and the credits are read from the same place, so a track cannot be
listed under two artists and billed for one.

Measured

/mnt/media/music, 4889 tracks, rows differing from upstream:

column before after
Genres 1403 59
AlbumArtists 50 50
Artists 13 0

and the albums summarised from them (#24) go from 141 differing Genres to 10.
ItemValues is 508 against upstream's 515, from 538.

What is left is where the two tag libraries collapse a repeated field
differently — a file naming ALBUMARTIST twice is two values to one and one to
the other — which is not reachable without ATL itself.

Left for later

  • #39 — the port bills 9328 people against upstream's 9151. That is who gets
    credited rather than how a tag is split.
Fixed in the merge of `fix/27-tag-splitting`. ## The rule could not be fixed as a rule The premise held — upstream reads a track with a tag library and splits only on that library's own separator — but no delimiter table could reproduce it, because ffprobe cannot say how many values a tag holds. Two files from this library, one whose genres upstream splits and one whose it does not: ``` A Silver Mt. Zion … .flac GENRE = 'Experimental;Post-Rock;Rock' AES Dana … .mp3 genre = 'Ambient;Downtempo;Electronic' ``` Identical to the prober. Upstream tells them apart because ATL reads the file: three Vorbis fields against one ID3 frame. Nor does the container predict it — of the FLACs upstream split 1317 and left 1302 whole. ## So the track is read twice As upstream reads one. The prober answers what is in the container; the file's own tags answer how many values a tag holds, and land in `MediaInfo::written`, a value per frame. A track's artists, album artists, genres and composers are read from there, and from what the prober made of the tag where no reader could open the file. A video is untouched: upstream reads one through the normalizer and never through a tag library, which is what the probe corpus records. The columns and the credits are read from the same place, so a track cannot be listed under two artists and billed for one. ## Measured `/mnt/media/music`, 4889 tracks, rows differing from upstream: | column | before | after | |---|---|---| | `Genres` | 1403 | 59 | | `AlbumArtists` | 50 | 50 | | `Artists` | 13 | 0 | and the albums summarised from them (#24) go from 141 differing `Genres` to 10. `ItemValues` is 508 against upstream's 515, from 538. What is left is where the two tag libraries collapse a repeated field differently — a file naming `ALBUMARTIST` twice is two values to one and one to the other — which is not reachable without ATL itself. ## Left for later - #39 — the port bills 9328 people against upstream's 9151. That is who gets credited rather than how a tag is split.
Sign in to join this conversation.
No description provided.