diff options
| author | Cody Robibero <cody@robibe.ro> | 2026-08-02 14:24:51 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-02 14:24:51 -0400 |
| commit | e2e3094d2d4e022cde3f688a44446853ca553b2b (patch) | |
| tree | 08800b91f7d9e5220ef2b2ad08dce6215dddde04 | |
| parent | d669994bf0ace09e7c189a75cb1ad1d8f8a9869e (diff) | |
| parent | d4376e0539577e922b99fd300520d78909c65aae (diff) | |
Merge pull request #17512 from altqx/libbitsub
Allow client-rendered graphical subtitles during remux
| -rw-r--r-- | MediaBrowser.Model/Dlna/StreamBuilder.cs | 6 | ||||
| -rw-r--r-- | tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs | 46 |
2 files changed, 48 insertions, 4 deletions
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index a9ab7d6db0..ab8d5dd5b2 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1582,7 +1582,11 @@ namespace MediaBrowser.Model.Dlna continue; } - if (!subtitleStream.IsExternal && playMethod == PlayMethod.Transcode && !transcoderSupport.CanExtractSubtitles(subtitleStream.Codec)) + if (!subtitleStream.IsExternal + && playMethod == PlayMethod.Transcode + && !transcoderSupport.CanExtractSubtitles(subtitleStream.Codec) + && !subtitleStream.IsPgsSubtitleStream + && !subtitleStream.IsVobSubSubtitleStream) { continue; } diff --git a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs index 5ba061296a..f5a023686c 100644 --- a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs +++ b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs @@ -371,6 +371,45 @@ namespace Jellyfin.Model.Tests Assert.Equal(streamInfo?.SubtitleStreamIndex, options.SubtitleStreamIndex); } + [Theory] + [InlineData("pgssub", null)] + [InlineData("vobsub", "mks")] + public async Task BuildVideoItemWithSecondaryAudioAndExternalGraphicalSubtitleKeepsVideoCopy(string subtitleCodec, string? subtitleContainer) + { + var options = await GetMediaOptions("Chrome", "mp4-h264-ac3-aac-srt-2600k"); + var subtitleStream = options.MediaSources[0].MediaStreams[^1]; + subtitleStream.Codec = subtitleCodec; + subtitleStream.IsExternal = false; + subtitleStream.SupportsExternalStream = true; + subtitleStream.Path = null; + + options.Profile.SubtitleProfiles = + [ + new SubtitleProfile + { + Format = subtitleCodec, + Container = subtitleContainer, + Method = SubtitleDeliveryMethod.External + } + ]; + options.AudioStreamIndex = 2; + options.SubtitleStreamIndex = subtitleStream.Index; + + var streamInfo = GetStreamBuilder(enableSubtitleExtraction: false).GetOptimalVideoStream(options); + + Assert.NotNull(streamInfo); + Assert.Equal(PlayMethod.Transcode, streamInfo.PlayMethod); + Assert.Equal(TranscodeReason.SecondaryAudioNotSupported, streamInfo.TranscodeReasons); + Assert.Equal(SubtitleDeliveryMethod.External, streamInfo.SubtitleDeliveryMethod); + Assert.Contains("h264", streamInfo.VideoCodecs); + Assert.Contains("aac", streamInfo.AudioCodecs); + + var queryString = streamInfo.ToUrl("media:", "ACCESSTOKEN", null).Split('?', 2).ElementAtOrDefault(1); + var query = System.Web.HttpUtility.ParseQueryString(queryString ?? string.Empty); + Assert.Null(query["SubtitleStreamIndex"]); + Assert.Null(query["SubtitleMethod"]); + } + private StreamInfo? BuildVideoItemSimpleTest(MediaOptions options, PlayMethod? playMethod, TranscodeReason why, string transcodeMode, string transcodeProtocol) { if (string.IsNullOrEmpty(transcodeProtocol)) @@ -573,9 +612,10 @@ namespace Jellyfin.Model.Tests throw new SerializationException("Invalid test data: " + name); } - private StreamBuilder GetStreamBuilder() + private StreamBuilder GetStreamBuilder(bool enableSubtitleExtraction = false) { var transcodeSupport = new Mock<ITranscoderSupport>(); + transcodeSupport.Setup(t => t.CanExtractSubtitles(It.IsAny<string>())).Returns(enableSubtitleExtraction); var logger = new NullLogger<StreamBuilderTests>(); return new StreamBuilder(transcodeSupport.Object, logger); @@ -625,7 +665,7 @@ namespace Jellyfin.Model.Tests // EnableSubtitleExtraction = false, internal subtitles [InlineData("srt", "srt", false, false, PlayMethod.Transcode, SubtitleDeliveryMethod.Encode)] [InlineData("srt", "srt", false, false, PlayMethod.DirectPlay, SubtitleDeliveryMethod.External)] - [InlineData("pgssub", "pgssub", false, false, PlayMethod.Transcode, SubtitleDeliveryMethod.Encode)] + [InlineData("pgssub", "pgssub", false, false, PlayMethod.Transcode, SubtitleDeliveryMethod.External)] [InlineData("pgssub", "pgssub", false, false, PlayMethod.DirectPlay, SubtitleDeliveryMethod.External)] [InlineData("pgssub", "srt", false, false, PlayMethod.Transcode, SubtitleDeliveryMethod.Encode)] // EnableSubtitleExtraction = false, external subtitles @@ -678,7 +718,7 @@ namespace Jellyfin.Model.Tests [Theory] [InlineData(false, null, true, SubtitleDeliveryMethod.External)] - [InlineData(false, null, false, SubtitleDeliveryMethod.Encode)] + [InlineData(false, null, false, SubtitleDeliveryMethod.External)] [InlineData(true, "/media/sub.mks", true, SubtitleDeliveryMethod.External)] [InlineData(true, "/media/sub.idx", true, SubtitleDeliveryMethod.Encode)] [InlineData(true, "/media/sub.sub", true, SubtitleDeliveryMethod.Encode)] |
