Skip to content

Commit

Permalink
fix: handle one-to-many video-subtitle mapping
Browse files Browse the repository at this point in the history
- Detect if multiple subtitles exist for a single video
- Retain language suffix if one-to-many mapping is found
- Improve merging of items with same keys
  - Group items by non-empty keys and merge them
  - Ensure the first non-empty video and all non-empty subtitles are kept
  - Keep items with empty keys unchanged
  - Update method signature to accept IReadOnlyList
  • Loading branch information
qwqcode committed Sep 23, 2024
1 parent 2f0ea7c commit 2376eb5
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 34 deletions.
61 changes: 31 additions & 30 deletions SubRenamer/Matcher/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,40 @@ public static class Helper
}
return "";
}

public static void MergeSameKeysItems(List<MatchItem> items)

/// <summary>
/// Merges items with the same non-empty keys by grouping them.
/// Assuming the mapping between the video and the subtitles is one-to-many (1 to N).
/// Each group is merged into a new list where the first non-empty video
/// is selected and all non-empty subtitles are kept.
/// </summary>
/// <param name="items">A read-only list of MatchItem objects to be merged by key.</param>
/// <returns>
/// A list of MatchItem objects where keys are merged, each key associated with
/// its first non-empty video and corresponding subtitles.
/// </returns>
public static List<MatchItem> MergeSameKeysItems(IReadOnlyList<MatchItem> items)
{
for (var i = 0; i < items.Count; i++)
// Group items by non-empty keys, filtering out items with null or empty keys
var groupedItems = items
.Where(item => !string.IsNullOrEmpty(item.Key))
.GroupBy(item => item.Key);

// Create the merged list of MatchItems
var result = new List<MatchItem>();
foreach (var group in groupedItems)
{
var item = items[i];
if (string.IsNullOrEmpty(item.Key)) continue;
//筛选出所有Subtitles用于匹配多个字幕
if (item.Subtitle != "")
{
for (var j = 0; j < items.Count; j++)
{
var other = items[j];
if (item.Key == other.Key && other.Subtitle == "")
{
item.Video = !string.IsNullOrEmpty(item.Video) ? item.Video : other.Video;
other.Status = "Paired";
}
}
}
//将已匹配完成的只包含Video的item删除
if (i == (items.Count - 1))
{
for (i = 0; i < items.Count; i++)
{
if (items[i].Status == "Paired")
{
items.RemoveAt(i);
i--;
}
}
}
var video = group.FirstOrDefault(item => !string.IsNullOrEmpty(item.Video))?.Video ?? "";
var subtitles = group.Where(item => !string.IsNullOrEmpty(item.Subtitle)).Select(item => item.Subtitle);

// Add a new MatchItem for each subtitle under the same key and video
result.AddRange(subtitles.Select(subtitle => new MatchItem(group.Key, video, subtitle)));
}

// Keep items with empty keys
result.AddRange(items.Where(item => string.IsNullOrEmpty(item.Key)));

return result;
}

public static void MoveEmptyKeyItemsToLast(List<MatchItem> items)
Expand Down
3 changes: 0 additions & 3 deletions SubRenamer/Services/DialogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ public async Task OpenItemEdit(MatchItem item, ObservableCollection<MatchItem> c
await dialog.ShowDialog(_target);
if (cancel) throw new UserCancelDialogException();
var selected = store.GetResult();
//选择全部保留时自动勾选保留语言后缀选项
var config = Config.Get();
if (selected == "全部保留") config.KeepLangExt = true;
return selected == "全部保留" ? null : selected;
}

Expand Down
7 changes: 6 additions & 1 deletion SubRenamer/Services/RenameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ public void UpdateRenameTaskList(IEnumerable<MatchItem> matchList, Collection<Re
{
destList.Clear();

// 检查是否存在视频字幕一对多的情况,若存在则保留语言后缀
// @see https://github.com/qwqcode/SubRenamer/pull/54
var hasOneVideo2ManySubtitles = matchList.GroupBy(x => x.Video).Any(g => g.Count() > 1);
var keepLangExt = Config.Get().KeepLangExt || hasOneVideo2ManySubtitles;

foreach (var item in matchList)
{
if (string.IsNullOrEmpty(item.Subtitle) || string.IsNullOrEmpty(item.Video)) continue;

// 提取字幕文件语言后缀
var subSuffix = "";
if (Config.Get().KeepLangExt) {
if (keepLangExt) {
var subSplit = Path.GetFileNameWithoutExtension(item.Subtitle).Split('.');
if (subSplit.Length > 1) subSuffix = "." + subSplit[^1];
}
Expand Down

0 comments on commit 2376eb5

Please sign in to comment.