Disambiguate Fetch Data's TMDB search results by name similarity
- New crates/renamr-core/src/similarity module: a partial port of the scoring idea behind FileBot's EpisodeMetrics.java - normalizes titles (lowercase, strips a trailing release-year parenthetical, collapses punctuation/whitespace) and scores them with a Sorensen-Dice coefficient over character bigrams. best_title_match() picks whichever candidate is textually closest to the query, provided it clears a minimum threshold; ties keep the earlier (i.e. TMDB-ranked) candidate. - TmdbClient::lookup_episode now uses best_title_match instead of blindly taking the first search result, so a more popular but differently-named show can no longer beat an exact-but-lower-ranked match to the top - and reports NotFound instead of guessing when nothing in the results is a plausible match at all. - 7 new tests (5 in similarity, 2 in tmdb) including the concrete regression case this fixes: searching "Chuck" with TMDB returning "Chucky" ranked above "Chuck" now correctly picks "Chuck". - Also fixes a gitignore gap from last delivery: the _to_delete*/ scratch-dir pattern used to work around this repo's mounted-folder git-lock quirk had only ever been applied directly on the device, never carried back into the zip this delivery is built from - so the last delivery's cp -rf silently reintroduced the untracked-lock-file risk. Fixed in both places now.
This commit is contained in:
@@ -7,11 +7,12 @@ fork), built from scratch as its own project: new stack, new architecture, new b
|
||||
engine is ported and tested, the faithfully-recreated two-pane UI is wired to real
|
||||
native file/folder loading and drag-and-drop, local filename-based season/episode
|
||||
detection ("Match") is working, real online metadata lookups against TMDB ("Fetch
|
||||
Data") are working, and the actual on-disk rename operation is wired up (same-directory
|
||||
rename, skip-on-conflict, with a confirmation step showing the full old-name/new-name
|
||||
plan before anything touches disk — there is no undo yet). Full media-metadata
|
||||
bindings and the fuzzy similarity/matching engine are not yet ported. See "Porting
|
||||
roadmap" below.
|
||||
Data") are working — including fuzzy show-name disambiguation, so a search that
|
||||
returns several similarly-named shows doesn't just take TMDB's top-ranked hit — and the
|
||||
actual on-disk rename operation is wired up (same-directory rename, skip-on-conflict,
|
||||
with a confirmation step showing the full old-name/new-name plan before anything
|
||||
touches disk — there is no undo yet). Full media-metadata bindings are not yet ported.
|
||||
See "Porting roadmap" below.
|
||||
|
||||
The naming scheme is fully user-editable from the app (the "Naming Scheme" button next
|
||||
to the New Names list) — the default is `{show name} - {season number}x{episode
|
||||
@@ -81,14 +82,16 @@ rendered output would be empty.
|
||||
|
||||
```
|
||||
crates/renamr-core/ Pure Rust core: naming-expression engine (ported), local
|
||||
filename-based season/episode matching (ported, `matching/`), a
|
||||
TMDB metadata client (`web/tmdb.rs` — TV search + episode lookup,
|
||||
tested against a mocked HTTP server via `mockito`), and the
|
||||
on-disk rename engine (ported for the same-directory case,
|
||||
`rename/`) — skip-on-conflict, no move/organize-into-folders yet.
|
||||
Not yet ported: the fuzzy similarity engine, full media metadata
|
||||
bindings, other web datasource clients (TVDB/AniDB/etc). No Tauri
|
||||
dependency, so it builds and unit-tests standalone.
|
||||
filename-based season/episode matching (ported, `matching/`),
|
||||
text-similarity scoring for disambiguating search results
|
||||
(`similarity/`, partial `EpisodeMetrics` port), a TMDB metadata
|
||||
client (`web/tmdb.rs` — TV search + episode lookup, disambiguated
|
||||
via `similarity/`, tested against a mocked HTTP server via
|
||||
`mockito`), and the on-disk rename engine (ported for the
|
||||
same-directory case, `rename/`) — skip-on-conflict, no
|
||||
move/organize-into-folders yet. Not yet ported: full media
|
||||
metadata bindings, other web datasource clients (TVDB/AniDB/etc).
|
||||
No Tauri dependency, so it builds and unit-tests standalone.
|
||||
src-tauri/ Tauri app shell: exposes renamr-core as commands to the frontend
|
||||
(naming-scheme rendering, filename matching, TMDB metadata fetch,
|
||||
executing a rename plan, native file/folder dialogs, drag-and-drop
|
||||
@@ -160,21 +163,25 @@ ported from, for anyone picking this up:
|
||||
3. **Matching/similarity engine** — `net.filebot.similarity.*`. Local filename-based
|
||||
season/episode detection is done (`crates/renamr-core/src/matching`, ported from the
|
||||
pattern-matching half of `SeasonEpisodeMatcher.java`, adapted to Rust's `regex` crate
|
||||
which lacks lookahead/lookbehind — wired to the "Match" button). Now that TMDB is
|
||||
wired up (see item 5 below), `EpisodeMetrics.java` (849 lines, the fuzzy title-matching
|
||||
score cascade) is the next thing this actually blocks on: today "Fetch Data" just
|
||||
takes TMDB's first (TMDB-ranked) search result, which is right most of the time but
|
||||
has no way to catch a wrong pick among several similarly-named shows. `DateMatcher`
|
||||
also still not ported.
|
||||
which lacks lookahead/lookbehind — wired to the "Match" button). Show-name
|
||||
disambiguation is also done (`crates/renamr-core/src/similarity`, a partial port of
|
||||
the *scoring* idea behind `EpisodeMetrics.java`'s fuzzy title-matching cascade —
|
||||
Sorensen-Dice similarity over normalized-title character bigrams): "Fetch Data" now
|
||||
picks whichever TMDB search result is textually closest to the local guess rather
|
||||
than just trusting TMDB's relevance/popularity-ranked first hit, and reports "not
|
||||
found" instead of guessing when nothing in the results is a plausible match at all.
|
||||
`DateMatcher` (numbering/air-date-based identification, the other half of the
|
||||
original `EpisodeMetrics`) is not ported — Renamr doesn't do date-based episode
|
||||
identification.
|
||||
4. **Media detection** — `net.filebot.media.MediaDetection` (1356 lines): ties file-name
|
||||
parsing + matching together to auto-identify what a file is.
|
||||
5. **Web datasource clients** — `net.filebot.web.*` (~40 files): TheMovieDB, TheTVDB,
|
||||
AniDB, OMDb, TVmaze, OpenSubtitles, etc. TMDB is done for TV (`crates/renamr-core/src/web/tmdb.rs`,
|
||||
`reqwest` + `serde_json`, Bearer-token auth) — search-by-name plus per-season episode
|
||||
lookup, wired to "Fetch Data". Picks the first (TMDB-ranked) search result rather
|
||||
than disambiguating between multiple plausible shows — a real fix needs the
|
||||
`EpisodeMetrics` fuzzy-matching port above. TMDB movie lookup and all other sources
|
||||
(TheTVDB, AniDB, OMDb, TVmaze, OpenSubtitles) are not yet started.
|
||||
lookup, wired to "Fetch Data", disambiguating multi-result searches via the
|
||||
similarity-scoring pass described in item 3 above rather than blindly trusting
|
||||
TMDB's top-ranked hit. TMDB movie lookup and all other sources (TheTVDB, AniDB,
|
||||
OMDb, TVmaze, OpenSubtitles) are not yet started.
|
||||
6. **Rename engine + CLI** — `net.filebot.cli.CmdlineOperations` (1235 lines) and
|
||||
`ArgumentBean` (415 lines, the full flag surface: `-rename`, `--db`, `--format`,
|
||||
`--action`, `--conflict`, `-get-subtitles`, `-script`, etc.). The core same-directory
|
||||
|
||||
Reference in New Issue
Block a user