Match and mux in dropped external subtitles
Drag in subtitle files alongside .mkv files and they're matched to the right video by episode code (S04E06, zero-padding and separator insensitive, plus 4x06 as a fallback) and muxed in as extra subtitle tracks. Any subtitle format mkvmerge accepts is recognized: SRT, (S)SA, VobSub, WebVTT, PGS/SUP, USF, SAMI, TTML/DFXP, STL, Kate. Matching works regardless of drop order — subtitles dropped before their video are held pending until a matching video shows up, and vice versa. Language, forced, and SDH flags are guessed from common filename tokens (e.g. "eng", "forced", "sdh") to set the muxed track's language/name/flags; unmatched subtitles are reported in the status bar.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Futonizer.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents one external subtitle file that was drag-and-dropped in and
|
||||
/// matched to a <see cref="QueuedFileItem"/> by episode code (e.g. S04E06),
|
||||
/// to be muxed in as an additional subtitle track when the file is processed.
|
||||
/// </summary>
|
||||
public class ExternalSubtitleTrack : INotifyPropertyChanged
|
||||
{
|
||||
private bool _isDefault;
|
||||
|
||||
public string FilePath { get; }
|
||||
public string FileName => Path.GetFileName(FilePath);
|
||||
|
||||
/// <summary>Uppercased extension without the dot, e.g. "SRT", "ASS", "SUP".</summary>
|
||||
public string FormatDisplay => Path.GetExtension(FilePath).TrimStart('.').ToUpperInvariant();
|
||||
|
||||
/// <summary>ISO 639-2 language code detected from the filename, or "und" if unknown.</summary>
|
||||
public string Language { get; init; } = "und";
|
||||
|
||||
/// <summary>Track name to embed in the output file; may be empty.</summary>
|
||||
public string TrackName { get; init; } = string.Empty;
|
||||
|
||||
public bool Forced { get; init; }
|
||||
public bool HearingImpaired { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this is the subtitle track flagged default in the output.
|
||||
/// Exactly one external subtitle per file should have this set at a time.
|
||||
/// </summary>
|
||||
public bool IsDefault
|
||||
{
|
||||
get => _isDefault;
|
||||
set
|
||||
{
|
||||
if (_isDefault == value) return;
|
||||
_isDefault = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Short "FORMAT · LANG" label shown as a chip in the UI.</summary>
|
||||
public string LanguageDisplay => $"{FormatDisplay} · {(string.Equals(Language, "und", StringComparison.OrdinalIgnoreCase) ? "UND" : Language.ToUpperInvariant())}";
|
||||
|
||||
public ExternalSubtitleTrack(string filePath)
|
||||
{
|
||||
FilePath = filePath;
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
private void OnPropertyChanged([CallerMemberName] string? name = null)
|
||||
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||
}
|
||||
Reference in New Issue
Block a user