A track's normalization gain is not read #72

Closed
opened 2026-08-04 16:06:58 +02:00 by Claude · 1 comment
Collaborator

A track's normalization gain is not read.

/Items?Recursive=true — 30 tracks carry a value upstream and none here:

track upstream ours
Funk Ad -5.75 absent
Garden Of Eden -10.08 absent

NormalizationGain is the ReplayGain a file declares. The BaseItems schema
has the column (LUFS, NormalizationGain) and this port writes neither, so a
client normalising playback volume has nothing to work from.

Upstream reads it during the probe. Worth checking which tag names it takes and
whether the value is the gain or is derived from LUFS.

A track's normalization gain is not read. `/Items?Recursive=true` — 30 tracks carry a value upstream and none here: | track | upstream | ours | |---|---|---| | Funk Ad | `-5.75` | absent | | Garden Of Eden | `-10.08` | absent | `NormalizationGain` is the ReplayGain a file declares. The `BaseItems` schema has the column (`LUFS`, `NormalizationGain`) and this port writes neither, so a client normalising playback volume has nothing to work from. Upstream reads it during the probe. Worth checking which tag names it takes and whether the value is the gain or is derived from LUFS.
Author
Collaborator

Fixed. Both were broken on the read path and the write path — the live
databases are upstream's own scan, so the columns were already populated and
this server still reported nothing.

NormalizationGain is not from the probe. AudioFileProber.cs:456 reads
the tag REPLAYGAIN_TRACK_GAIN out of the tag library's additional fields,
strips a case-insensitive db suffix, and stores it if it parses finite —
audio only. DtoService.cs:1144 answers -18 - LUFS when a LUFS is stored and
the gain otherwise. LUFS itself is written only by a scheduled loudness pass
this port does not run.

That the tag library reads it rather than ffprobe is load-bearing: 42 of the
83 gain-carrying files in the library are MP3s whose gain lives in an APEv2 tag
ffprobe does not report at all.

IndexNumberEnd has no column — it is serialized into BaseItems.Data.
jellyfin-naming already parsed it correctly; the scan dropped it, the write
never carried it, and the read never looked in the blob.

field before after
NormalizationGain 30 0
IndexNumberEnd 11 0

Gains from a real scan of six library files are bit-identical to upstream's
answer key, and a rescan still writes nothing — every row's Data,
DateLastSaved and NormalizationGain byte-identical after a second pass.

Fixed. Both were broken on the read path **and** the write path — the live databases are upstream's own scan, so the columns were already populated and this server still reported nothing. **`NormalizationGain`** is not from the probe. `AudioFileProber.cs:456` reads the tag `REPLAYGAIN_TRACK_GAIN` out of the tag library's additional fields, strips a case-insensitive `db` suffix, and stores it if it parses finite — audio only. `DtoService.cs:1144` answers `-18 - LUFS` when a LUFS is stored and the gain otherwise. `LUFS` itself is written only by a scheduled loudness pass this port does not run. That the tag library reads it rather than ffprobe is load-bearing: **42 of the 83 gain-carrying files in the library are MP3s whose gain lives in an APEv2 tag ffprobe does not report at all.** **`IndexNumberEnd`** has no column — it is serialized into `BaseItems.Data`. `jellyfin-naming` already parsed it correctly; the scan dropped it, the write never carried it, and the read never looked in the blob. | field | before | after | |---|---|---| | `NormalizationGain` | 30 | **0** | | `IndexNumberEnd` | 11 | **0** | Gains from a real scan of six library files are bit-identical to upstream's answer key, and a rescan still writes nothing — every row's `Data`, `DateLastSaved` and `NormalizationGain` byte-identical after a second pass.
Sign in to join this conversation.
No description provided.