diff --git a/lib/services/track_manager.dart b/lib/services/track_manager.dart index 53d408a1..a1863283 100644 --- a/lib/services/track_manager.dart +++ b/lib/services/track_manager.dart @@ -274,7 +274,7 @@ class TrackManager { if (streamID != null) { appLogger.d('Matched audio by lang/title: streamID $streamID'); } else { - final matchedPlex = findPlexTrackForMpvAudio(track, info.audioTracks); + final matchedPlex = findPlexTrackForMpvAudio(track, info.audioTracks, allMpvTracks: player.state.tracks.audio); streamID = matchedPlex?.id; if (streamID != null) { appLogger.d('Matched audio by properties: streamID $streamID'); @@ -315,7 +315,7 @@ class TrackManager { if (streamID != null) { appLogger.d('Matched subtitle by lang/title: streamID $streamID'); } else { - final matchedPlex = findPlexTrackForMpvSubtitle(track, info.subtitleTracks); + final matchedPlex = findPlexTrackForMpvSubtitle(track, info.subtitleTracks, allMpvTracks: player.state.tracks.subtitle); streamID = matchedPlex?.id; if (streamID != null) { appLogger.d('Matched subtitle by properties: streamID $streamID'); diff --git a/lib/services/track_selection_service.dart b/lib/services/track_selection_service.dart index c1cc99a5..9a7a1d83 100644 --- a/lib/services/track_selection_service.dart +++ b/lib/services/track_selection_service.dart @@ -16,7 +16,7 @@ import '../utils/language_codes.dart'; // differently. /// Find the MPV subtitle track that matches a Plex subtitle track -SubtitleTrack? findMpvTrackForPlexSubtitle(PlexSubtitleTrack plexTrack, List mpvTracks) { +SubtitleTrack? findMpvTrackForPlexSubtitle(PlexSubtitleTrack plexTrack, List mpvTracks, {List? allPlexTracks}) { if (mpvTracks.isEmpty) return null; // For external subtitles, match by URI containing the Plex key @@ -35,6 +35,10 @@ SubtitleTrack? findMpvTrackForPlexSubtitle(PlexSubtitleTrack plexTrack, List !t.isExternal).toList() : null; + final plexOrdinal = allPlexTracks != null ? allPlexTracks.where((t) => !t.isExternal).toList().indexOf(plexTrack) : -1; + for (final mpvTrack in mpvTracks) { // Skip external tracks when matching internal Plex tracks if (!plexTrack.isExternal && mpvTrack.isExternal) continue; @@ -64,6 +68,15 @@ SubtitleTrack? findMpvTrackForPlexSubtitle(PlexSubtitleTrack plexTrack, List= 0) { + final mpvOrdinal = internalMpvTracks.indexOf(mpvTrack); + if (mpvOrdinal >= 0 && plexOrdinal == mpvOrdinal) { + score += 1; + } + } + if (score > bestScore) { bestScore = score; bestMatch = mpvTrack; @@ -75,7 +88,7 @@ SubtitleTrack? findMpvTrackForPlexSubtitle(PlexSubtitleTrack plexTrack, List plexTracks) { +PlexSubtitleTrack? findPlexTrackForMpvSubtitle(SubtitleTrack mpvTrack, List plexTracks, {List? allMpvTracks}) { if (plexTracks.isEmpty) return null; // For external subtitles, match by URI containing the Plex key @@ -93,6 +106,10 @@ PlexSubtitleTrack? findPlexTrackForMpvSubtitle(SubtitleTrack mpvTrack, List !t.isExternal).toList() : null; + final mpvOrdinal = allMpvTracks != null ? allMpvTracks.where((t) => !t.isExternal).toList().indexOf(mpvTrack) : -1; + for (final plexTrack in plexTracks) { // Skip external Plex tracks when matching internal MPV tracks if (!mpvTrack.isExternal && plexTrack.isExternal) continue; @@ -122,6 +139,14 @@ PlexSubtitleTrack? findPlexTrackForMpvSubtitle(SubtitleTrack mpvTrack, List= 0) { + final plexOrdinal = internalPlexTracks.indexOf(plexTrack); + if (plexOrdinal >= 0 && mpvOrdinal == plexOrdinal) { + score += 1; + } + } + if (score > bestScore) { bestScore = score; bestMatch = plexTrack; @@ -133,11 +158,12 @@ PlexSubtitleTrack? findPlexTrackForMpvSubtitle(SubtitleTrack mpvTrack, List mpvTracks) { +AudioTrack? findMpvTrackForPlexAudio(PlexAudioTrack plexTrack, List mpvTracks, {List? allPlexTracks}) { if (mpvTracks.isEmpty) return null; AudioTrack? bestMatch; int bestScore = 0; + final plexOrdinal = allPlexTracks?.indexOf(plexTrack) ?? -1; for (final mpvTrack in mpvTracks) { int score = 0; @@ -167,6 +193,14 @@ AudioTrack? findMpvTrackForPlexAudio(PlexAudioTrack plexTrack, List score += 2; } + // Ordinal position tiebreaker (+1) + if (plexOrdinal >= 0) { + final mpvOrdinal = mpvTracks.indexOf(mpvTrack); + if (mpvOrdinal >= 0 && plexOrdinal == mpvOrdinal) { + score += 1; + } + } + if (score > bestScore) { bestScore = score; bestMatch = mpvTrack; @@ -178,11 +212,12 @@ AudioTrack? findMpvTrackForPlexAudio(PlexAudioTrack plexTrack, List } /// Find the Plex audio track that matches an MPV audio track -PlexAudioTrack? findPlexTrackForMpvAudio(AudioTrack mpvTrack, List plexTracks) { +PlexAudioTrack? findPlexTrackForMpvAudio(AudioTrack mpvTrack, List plexTracks, {List? allMpvTracks}) { if (plexTracks.isEmpty) return null; PlexAudioTrack? bestMatch; int bestScore = 0; + final mpvOrdinal = allMpvTracks?.indexOf(mpvTrack) ?? -1; for (final plexTrack in plexTracks) { int score = 0; @@ -212,6 +247,14 @@ PlexAudioTrack? findPlexTrackForMpvAudio(AudioTrack mpvTrack, List= 0) { + final plexOrdinal = plexTracks.indexOf(plexTrack); + if (plexOrdinal >= 0 && mpvOrdinal == plexOrdinal) { + score += 1; + } + } + if (score > bestScore) { bestScore = score; bestMatch = plexTrack; @@ -541,7 +584,7 @@ class TrackSelectionService { final plexSelectedTrack = plexMediaInfo!.audioTracks.where((t) => t.selected).firstOrNull; if (plexSelectedTrack != null) { - final matchedMpvTrack = findMpvTrackForPlexAudio(plexSelectedTrack, availableTracks); + final matchedMpvTrack = findMpvTrackForPlexAudio(plexSelectedTrack, availableTracks, allPlexTracks: plexMediaInfo!.audioTracks); if (matchedMpvTrack != null) { return TrackSelectionResult(matchedMpvTrack, TrackSelectionPriority.plexSelected); @@ -603,7 +646,7 @@ class TrackSelectionService { final plexSelectedTrack = plexMediaInfo!.subtitleTracks.where((t) => t.selected).firstOrNull; if (plexSelectedTrack != null) { - final matchedMpvTrack = findMpvTrackForPlexSubtitle(plexSelectedTrack, availableTracks); + final matchedMpvTrack = findMpvTrackForPlexSubtitle(plexSelectedTrack, availableTracks, allPlexTracks: plexMediaInfo!.subtitleTracks); if (matchedMpvTrack != null) { return TrackSelectionResult(matchedMpvTrack, TrackSelectionPriority.plexSelected);