fix: subtitle track matching (forced flag parsing, title scoring)

This commit is contained in:
edde746
2026-04-03 23:53:37 +02:00
parent 7d35132509
commit 3c59452782
2 changed files with 19 additions and 17 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ class PlexMediaInfo {
title: s['title'] as String?, title: s['title'] as String?,
displayTitle: s['displayTitle'] as String?, displayTitle: s['displayTitle'] as String?,
selected: s['selected'] == 1 || s['selected'] == true, selected: s['selected'] == 1 || s['selected'] == true,
forced: s['forced'] == 1, forced: s['forced'] == 1 || s['forced'] == true,
key: s['key'] as String?, key: s['key'] as String?,
)); ));
} }
+18 -16
View File
@@ -58,10 +58,8 @@ SubtitleTrack? findMpvTrackForPlexSubtitle(PlexSubtitleTrack plexTrack, List<Sub
score += 5; score += 5;
} }
// Title match (+3) // Title match (+3 for text match, +1 for null/empty)
if (_titlesMatch(mpvTrack.title, plexTrack.title, plexTrack.displayTitle)) { score += _titleScore(mpvTrack.title, plexTrack.title, plexTrack.displayTitle);
score += 3;
}
// Forced flag match (+2) // Forced flag match (+2)
if (mpvTrack.isForced == plexTrack.forced) { if (mpvTrack.isForced == plexTrack.forced) {
@@ -129,10 +127,8 @@ PlexSubtitleTrack? findPlexTrackForMpvSubtitle(SubtitleTrack mpvTrack, List<Plex
score += 5; score += 5;
} }
// Title match (+3) // Title match (+3 for text match, +1 for null/empty)
if (_titlesMatch(mpvTrack.title, plexTrack.title, plexTrack.displayTitle)) { score += _titleScore(mpvTrack.title, plexTrack.title, plexTrack.displayTitle);
score += 3;
}
// Forced flag match (+2) // Forced flag match (+2)
if (mpvTrack.isForced == plexTrack.forced) { if (mpvTrack.isForced == plexTrack.forced) {
@@ -345,21 +341,27 @@ bool _audioCodecsMatch(String? mpvCodec, String? plexCodec) {
return mpvAliases.contains(plexNorm); return mpvAliases.contains(plexNorm);
} }
/// Check if titles match (fuzzy comparison) /// Score how well titles match.
bool _titlesMatch(String? mpvTitle, String? plexTitle, String? plexDisplayTitle) { /// Returns 3 for a real text match, 1 for null/empty (non-contradicting), 0 for mismatch.
if (mpvTitle == null || mpvTitle.isEmpty) return true; // No title to match against int _titleScore(String? mpvTitle, String? plexTitle, String? plexDisplayTitle) {
if (mpvTitle == null || mpvTitle.isEmpty) return 1; // No title to contradict — mild bonus
final mpvNorm = mpvTitle.toLowerCase().trim(); final mpvNorm = mpvTitle.toLowerCase().trim();
// Check exact match with either Plex title // Check exact match with either Plex title
if (plexTitle != null && plexTitle.toLowerCase().trim() == mpvNorm) return true; if (plexTitle != null && plexTitle.toLowerCase().trim() == mpvNorm) return 3;
if (plexDisplayTitle != null && plexDisplayTitle.toLowerCase().trim() == mpvNorm) return true; if (plexDisplayTitle != null && plexDisplayTitle.toLowerCase().trim() == mpvNorm) return 3;
// Check if one contains the other (partial match) // Check if one contains the other (partial match)
if (plexTitle != null && plexTitle.toLowerCase().contains(mpvNorm)) return true; if (plexTitle != null && plexTitle.toLowerCase().contains(mpvNorm)) return 3;
if (plexDisplayTitle != null && plexDisplayTitle.toLowerCase().contains(mpvNorm)) return true; if (plexDisplayTitle != null && plexDisplayTitle.toLowerCase().contains(mpvNorm)) return 3;
return false; return 0;
}
/// Check if titles match (fuzzy comparison) — used by audio matching
bool _titlesMatch(String? mpvTitle, String? plexTitle, String? plexDisplayTitle) {
return _titleScore(mpvTitle, plexTitle, plexDisplayTitle) > 0;
} }
/// Priority levels for track selection /// Priority levels for track selection