3.0 KiB
name, description
| name | description |
|---|---|
| plex-metadata-title-cache-read | Read the live Plex library DB read-only for clean titles/file paths (no sqlite3 binary, server running), and use it as the title authority over filename parsing. |
Plex's metadata cache already holds a clean title for every file it matched
(Alien, not Alien.Directors.Cut.1979.1080p.BRrip.x265-RARBG). Read it instead
of parsing filenames, and name folders / group duplicates from it.
Where it lives
Host package: data dir /var/lib/plexmediaserver, DB at
/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db
(Resources/com.plexapp.plugins.library.db under /usr/lib/plexmediaserver is a
blank template — not the library.) The dir is dank:dank, so no sudo needed.
Containers: check podman ps first; on Dankserver Plex runs as a host process.
Read it while Plex is RUNNING
No sqlite3 binary on the fleet hosts — use python3 -c with sqlite3. Open
immutable read-only so no WAL/SHM is touched and no lock is taken:
con = sqlite3.connect(f"file:{db}?mode=ro&immutable=1", uri=True)
A long local find / can hit the tool's own deadline; scope find with
-maxdepth or use the path above directly.
Schema traps
library_sections→ column issection_type, nottype. Movies = 1, TV = 2, Music = 8.metadata_titlesdoes not exist (empty name in the table list). Titles are onmetadata_items:title,original_title,edition_title,year,metadata_type,parent_id,deleted_at.- File path is
media_parts.file; joinmedia_parts → media_items (id = media_item_id) → metadata_items (id = metadata_item_id), andLEFT JOIN metadata_items par ON par.id = mi.parent_idfor the show/movie parent. - Movies use the LEAF title (
mi.title); the parent row is empty. TV uses the parent. Filterp.deleted_at IS NULL AND mi.deleted_at IS NULLor deleted scans pollute the census.
select p.file, mi.title, mi.original_title, mi.edition_title, mi.year, m.container,
m.video_codec, m.audio_codec, m.width, m.height
from media_parts p
join media_items m on m.id = p.media_item_id
join metadata_items mi on mi.id = m.metadata_item_id
where p.file like '/mnt/entropy/Movies/%'
and p.deleted_at is null and mi.deleted_at is null
media_items also carries codec/resolution already — often no ffprobe pass is
needed for matched files.
Use it as the title authority
Reject a Plex title only if it looks like a filename
(2160p|1080p|x26[45]|hevc|bluray|web-?dl) — a healthy cache scores 0 junk
titles. Coverage expectation measured on /mnt/entropy/Movies: 3,754 of 4,698
media files matched; the unmatched remainder is extras, BDMV disc trees, TV
episodes misfiled into Movies, and collection box sets — exactly the classes a
filename parser must still handle.
Propagate one match to every copy of a film (a group of versions) so sidecars,
.nfo and media files share one stem; fall back to the filename parser only
when no row exists.