AttachmentStreamInfos is never written, so embedded fonts are lost #13

Closed
opened 2026-08-02 14:27:23 +02:00 by Claude · 1 comment
Collaborator

AttachmentStreamInfos holds 225 rows upstream and 0 here.

Matroska attachments are mostly fonts, and they are what an ASS subtitle needs
to render as authored. Without the rows there is nothing to extract at playback
time, so styled subtitles fall back to whatever the renderer has.

jellyfin-core/src/rows.rs and jellyfin-db/src/items.rs already read the
table.


Found by scanning /mnt/media (285 movies, 289 shows, 74 music artists —
~13 000 media files on a CIFS mount) with both this server and upstream
Jellyfin at the pinned commit, remote metadata and image fetchers disabled on
upstream so both were reading files only. Upstream was given the same mount
path so MD5(UTF-16LE(path)) agrees and rows compare directly.

`AttachmentStreamInfos` holds 225 rows upstream and 0 here. Matroska attachments are mostly fonts, and they are what an ASS subtitle needs to render as authored. Without the rows there is nothing to extract at playback time, so styled subtitles fall back to whatever the renderer has. `jellyfin-core/src/rows.rs` and `jellyfin-db/src/items.rs` already read the table. --- Found by scanning `/mnt/media` (285 movies, 289 shows, 74 music artists — ~13 000 media files on a CIFS mount) with both this server and upstream Jellyfin at the pinned commit, remote metadata and image fetchers disabled on upstream so both were reading files only. Upstream was given the same mount path so `MD5(UTF-16LE(path))` agrees and rows compare directly.
Author
Collaborator

Fixed in a50d74a and 7648dfa.

Verified against the real library: 225 rows, every column of every one of them
upstream's — nothing differing, nothing missing, nothing ours alone
(was 0
rows).

upstream ours
AttachmentStreamInfos 225 225
rows whose columns disagree 0
rows either side has alone 0

108 covers, 60 fonts, and the rest whatever else was muxed in. The prober
already read them; nothing carried them from the pass to the table.

A track's own cover is not one of these — upstream files what is muxed into a
video and nothing else — and a folder has no file to have anything muxed into.


Review found that the rows would have reached nobody: every media source
answered with an empty attachment list, so a client had no way to learn a font
was there even once the table held one. 7648dfa fills it, and a client that
asks how to play a source is told where each attachment is — the one place
upstream names a url for them. The route that url points at is still
unimplemented, which ENDPOINTS.md already records.

Fixed in `a50d74a` and `7648dfa`. **Verified against the real library: 225 rows, every column of every one of them upstream's — nothing differing, nothing missing, nothing ours alone** (was 0 rows). | | upstream | ours | |---|---|---| | `AttachmentStreamInfos` | 225 | **225** | | rows whose columns disagree | | 0 | | rows either side has alone | | 0 | 108 covers, 60 fonts, and the rest whatever else was muxed in. The prober already read them; nothing carried them from the pass to the table. A track's own cover is not one of these — upstream files what is muxed into a video and nothing else — and a folder has no file to have anything muxed into. --- Review found that the rows would have reached nobody: every media source answered with an empty attachment list, so a client had no way to learn a font was there even once the table held one. `7648dfa` fills it, and a client that asks how to play a source is told where each attachment is — the one place upstream names a url for them. The route that url points at is still unimplemented, which `ENDPOINTS.md` already records.
Sign in to join this conversation.
No description provided.