Match VobSub MKS subtitle profiles by container

This commit is contained in:
altqx
2026-07-03 09:30:22 +07:00
parent 8f3eb3205d
commit 8622c3bfb7
2 changed files with 62 additions and 10 deletions
+20 -10
View File
@@ -576,11 +576,8 @@ namespace MediaBrowser.Model.Dlna
foreach (var profile in subtitleProfiles)
{
if (profile.Method == SubtitleDeliveryMethod.External
&& (string.Equals(profile.Format, stream.Codec, StringComparison.OrdinalIgnoreCase)
// FFmpeg cannot mux VobSub back into an .idx/.sub pair, so extracted VobSub streams are exposed as .mks.
|| (string.Equals(profile.Format, "mks", StringComparison.OrdinalIgnoreCase)
&& stream.IsVobSubSubtitleStream
&& (!stream.IsExternal || stream.Path.EndsWith(".mks", StringComparison.OrdinalIgnoreCase)))))
&& (IsVobSubMksProfile(profile, stream)
|| (!IsVobSubMksDeliveryProfile(profile) && string.Equals(profile.Format, stream.Codec, StringComparison.OrdinalIgnoreCase))))
{
return stream.Index;
}
@@ -1590,13 +1587,11 @@ namespace MediaBrowser.Model.Dlna
continue;
}
// FFmpeg cannot mux VobSub back into an .idx/.sub pair, so extracted VobSub streams are matched against external .mks delivery profiles.
bool isVobSubMksProfile = string.Equals(profile.Format, "mks", StringComparison.OrdinalIgnoreCase)
&& subtitleStream.IsVobSubSubtitleStream
&& (!subtitleStream.IsExternal || subtitleStream.Path.EndsWith(".mks", StringComparison.OrdinalIgnoreCase));
bool isVobSubMksProfile = IsVobSubMksProfile(profile, subtitleStream);
if ((profile.Method == SubtitleDeliveryMethod.External
&& (isVobSubMksProfile || subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))) ||
&& (isVobSubMksProfile
|| (!IsVobSubMksDeliveryProfile(profile) && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format)))) ||
(profile.Method == SubtitleDeliveryMethod.Hls && subtitleStream.IsTextSubtitleStream))
{
bool requiresConversion = !isVobSubMksProfile
@@ -1628,6 +1623,21 @@ namespace MediaBrowser.Model.Dlna
return null;
}
private static bool IsVobSubMksDeliveryProfile(SubtitleProfile profile)
{
return MediaStream.IsVobSubFormat(profile.Format)
&& !string.IsNullOrWhiteSpace(profile.Container)
&& ContainerHelper.ContainsContainer(profile.Container, "mks");
}
private static bool IsVobSubMksProfile(SubtitleProfile profile, MediaStream subtitleStream)
{
// FFmpeg cannot mux VobSub back into an .idx/.sub pair, so extracted VobSub streams are exposed as .mks.
return IsVobSubMksDeliveryProfile(profile)
&& subtitleStream.IsVobSubSubtitleStream
&& (!subtitleStream.IsExternal || subtitleStream.Path?.EndsWith(".mks", StringComparison.OrdinalIgnoreCase) == true);
}
private bool IsBitrateLimitExceeded(MediaSourceInfo item, long maxBitrate)
{
// Don't restrict bitrate if item is remote.
@@ -676,6 +676,48 @@ namespace Jellyfin.Model.Tests
Assert.Equal(expectedMethod, result.Method);
}
[Theory]
[InlineData(false, null, true, SubtitleDeliveryMethod.External)]
[InlineData(false, null, false, SubtitleDeliveryMethod.Encode)]
[InlineData(true, "/media/sub.mks", true, SubtitleDeliveryMethod.External)]
[InlineData(true, "/media/sub.idx", true, SubtitleDeliveryMethod.Encode)]
[InlineData(true, "/media/sub.sub", true, SubtitleDeliveryMethod.Encode)]
public void GetSubtitleProfile_MatchesVobSubMksProfileOnlyWhenDeliveredAsMks(
bool isExternal,
string? path,
bool enableSubtitleExtraction,
SubtitleDeliveryMethod expectedMethod)
{
var mediaSource = new MediaSourceInfo();
var subtitleStream = new MediaStream
{
Type = MediaStreamType.Subtitle,
Index = 0,
IsExternal = isExternal,
Path = path,
Codec = "vobsub"
};
var subtitleProfiles = new[]
{
new SubtitleProfile { Format = "vobsub", Container = "mks", Method = SubtitleDeliveryMethod.External }
};
var transcoderSupport = new Mock<ITranscoderSupport>();
transcoderSupport.Setup(t => t.CanExtractSubtitles(It.IsAny<string>())).Returns(enableSubtitleExtraction);
var result = StreamBuilder.GetSubtitleProfile(
mediaSource,
subtitleStream,
subtitleProfiles,
PlayMethod.Transcode,
transcoderSupport.Object,
null,
null);
Assert.Equal(expectedMethod, result.Method);
}
[Theory]
// External text subs embedded into MKV when transcoding (#16403)
[InlineData("srt", true, PlayMethod.Transcode, "mkv", MediaStreamProtocol.http, SubtitleDeliveryMethod.Embed)]