Ver código fonte

Add option to always burn in subtitles if transcoding is triggered (#12430)

gnattu 8 meses atrás
pai
commit
62712aa12c

+ 8 - 3
Jellyfin.Api/Controllers/MediaInfoController.cs

@@ -209,6 +209,7 @@ public class MediaInfoController : BaseJellyfinApiController
                     enableTranscoding.Value,
                     allowVideoStreamCopy.Value,
                     allowAudioStreamCopy.Value,
+                    playbackInfoDto?.AlwaysBurnInSubtitleWhenTranscoding ?? false,
                     Request.HttpContext.GetNormalizedRemoteIP());
             }
 
@@ -236,7 +237,8 @@ public class MediaInfoController : BaseJellyfinApiController
                         StartTimeTicks = startTimeTicks,
                         SubtitleStreamIndex = subtitleStreamIndex,
                         UserId = userId ?? Guid.Empty,
-                        OpenToken = mediaSource.OpenToken
+                        OpenToken = mediaSource.OpenToken,
+                        AlwaysBurnInSubtitleWhenTranscoding = playbackInfoDto?.AlwaysBurnInSubtitleWhenTranscoding ?? false
                     }).ConfigureAwait(false);
 
                 info.MediaSources = new[] { openStreamResult.MediaSource };
@@ -261,6 +263,7 @@ public class MediaInfoController : BaseJellyfinApiController
     /// <param name="openLiveStreamDto">The open live stream dto.</param>
     /// <param name="enableDirectPlay">Whether to enable direct play. Default: true.</param>
     /// <param name="enableDirectStream">Whether to enable direct stream. Default: true.</param>
+    /// <param name="alwaysBurnInSubtitleWhenTranscoding">Always burn-in subtitle when transcoding.</param>
     /// <response code="200">Media source opened.</response>
     /// <returns>A <see cref="Task"/> containing a <see cref="LiveStreamResponse"/>.</returns>
     [HttpPost("LiveStreams/Open")]
@@ -277,7 +280,8 @@ public class MediaInfoController : BaseJellyfinApiController
         [FromQuery] Guid? itemId,
         [FromBody] OpenLiveStreamDto? openLiveStreamDto,
         [FromQuery] bool? enableDirectPlay,
-        [FromQuery] bool? enableDirectStream)
+        [FromQuery] bool? enableDirectStream,
+        [FromQuery] bool? alwaysBurnInSubtitleWhenTranscoding)
     {
         userId ??= openLiveStreamDto?.UserId;
         userId = RequestHelpers.GetUserId(User, userId);
@@ -295,7 +299,8 @@ public class MediaInfoController : BaseJellyfinApiController
             DeviceProfile = openLiveStreamDto?.DeviceProfile,
             EnableDirectPlay = enableDirectPlay ?? openLiveStreamDto?.EnableDirectPlay ?? true,
             EnableDirectStream = enableDirectStream ?? openLiveStreamDto?.EnableDirectStream ?? true,
-            DirectPlayProtocols = openLiveStreamDto?.DirectPlayProtocols ?? new[] { MediaProtocol.Http }
+            DirectPlayProtocols = openLiveStreamDto?.DirectPlayProtocols ?? new[] { MediaProtocol.Http },
+            AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding ?? openLiveStreamDto?.AlwaysBurnInSubtitleWhenTranscoding ?? false
         };
         return await _mediaInfoHelper.OpenMediaSource(HttpContext, request).ConfigureAwait(false);
     }

+ 1 - 0
Jellyfin.Api/Controllers/UniversalAudioController.cs

@@ -160,6 +160,7 @@ public class UniversalAudioController : BaseJellyfinApiController
                 true,
                 true,
                 true,
+                false,
                 Request.HttpContext.GetNormalizedRemoteIP());
         }
 

+ 5 - 1
Jellyfin.Api/Helpers/MediaInfoHelper.cs

@@ -156,6 +156,7 @@ public class MediaInfoHelper
     /// <param name="enableTranscoding">Enable transcoding.</param>
     /// <param name="allowVideoStreamCopy">Allow video stream copy.</param>
     /// <param name="allowAudioStreamCopy">Allow audio stream copy.</param>
+    /// <param name="alwaysBurnInSubtitleWhenTranscoding">Always burn-in subtitle when transcoding.</param>
     /// <param name="ipAddress">Requesting IP address.</param>
     public void SetDeviceSpecificData(
         BaseItem item,
@@ -175,6 +176,7 @@ public class MediaInfoHelper
         bool enableTranscoding,
         bool allowVideoStreamCopy,
         bool allowAudioStreamCopy,
+        bool alwaysBurnInSubtitleWhenTranscoding,
         IPAddress ipAddress)
     {
         var streamBuilder = new StreamBuilder(_mediaEncoder, _logger);
@@ -188,7 +190,8 @@ public class MediaInfoHelper
             Profile = profile,
             MaxAudioChannels = maxAudioChannels,
             AllowAudioStreamCopy = allowAudioStreamCopy,
-            AllowVideoStreamCopy = allowVideoStreamCopy
+            AllowVideoStreamCopy = allowVideoStreamCopy,
+            AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding,
         };
 
         if (string.Equals(mediaSourceId, mediaSource.Id, StringComparison.OrdinalIgnoreCase))
@@ -420,6 +423,7 @@ public class MediaInfoHelper
                 true,
                 true,
                 true,
+                request.AlwaysBurnInSubtitleWhenTranscoding,
                 httpContext.GetNormalizedRemoteIP());
         }
         else

+ 5 - 0
Jellyfin.Api/Models/MediaInfoDtos/OpenLiveStreamDto.cs

@@ -65,6 +65,11 @@ public class OpenLiveStreamDto
     /// </summary>
     public bool? EnableDirectStream { get; set; }
 
+    /// <summary>
+    /// Gets or sets a value indicating whether always burn in subtitles when transcoding.
+    /// </summary>
+    public bool? AlwaysBurnInSubtitleWhenTranscoding { get; set; }
+
     /// <summary>
     /// Gets or sets the device profile.
     /// </summary>

+ 5 - 0
Jellyfin.Api/Models/MediaInfoDtos/PlaybackInfoDto.cs

@@ -82,4 +82,9 @@ public class PlaybackInfoDto
     /// Gets or sets a value indicating whether to auto open the live stream.
     /// </summary>
     public bool? AutoOpenLiveStream { get; set; }
+
+    /// <summary>
+    /// Gets or sets a value indicating whether always burn in subtitles when transcoding.
+    /// </summary>
+    public bool? AlwaysBurnInSubtitleWhenTranscoding { get; set; }
 }

+ 5 - 0
MediaBrowser.Model/Dlna/MediaOptions.cs

@@ -49,6 +49,11 @@ namespace MediaBrowser.Model.Dlna
         /// </summary>
         public bool AllowVideoStreamCopy { get; set; }
 
+        /// <summary>
+        /// Gets or sets a value indicating whether always burn in subtitles when transcoding.
+        /// </summary>
+        public bool AlwaysBurnInSubtitleWhenTranscoding { get; set; }
+
         /// <summary>
         /// Gets or sets the item id.
         /// </summary>

+ 16 - 4
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -20,8 +20,8 @@ namespace MediaBrowser.Model.Dlna
         // Aliases
         internal const TranscodeReason ContainerReasons = TranscodeReason.ContainerNotSupported | TranscodeReason.ContainerBitrateExceedsLimit;
         internal const TranscodeReason AudioReasons = TranscodeReason.AudioCodecNotSupported | TranscodeReason.AudioBitrateNotSupported | TranscodeReason.AudioChannelsNotSupported | TranscodeReason.AudioProfileNotSupported | TranscodeReason.AudioSampleRateNotSupported | TranscodeReason.SecondaryAudioNotSupported | TranscodeReason.AudioBitDepthNotSupported | TranscodeReason.AudioIsExternal;
-        internal const TranscodeReason VideoReasons = TranscodeReason.VideoCodecNotSupported | TranscodeReason.VideoResolutionNotSupported | TranscodeReason.AnamorphicVideoNotSupported | TranscodeReason.InterlacedVideoNotSupported | TranscodeReason.VideoBitDepthNotSupported | TranscodeReason.VideoBitrateNotSupported | TranscodeReason.VideoFramerateNotSupported | TranscodeReason.VideoLevelNotSupported | TranscodeReason.RefFramesNotSupported;
-        internal const TranscodeReason DirectStreamReasons = AudioReasons | TranscodeReason.ContainerNotSupported;
+        internal const TranscodeReason VideoReasons = TranscodeReason.VideoCodecNotSupported | TranscodeReason.VideoResolutionNotSupported | TranscodeReason.AnamorphicVideoNotSupported | TranscodeReason.InterlacedVideoNotSupported | TranscodeReason.VideoBitDepthNotSupported | TranscodeReason.VideoBitrateNotSupported | TranscodeReason.VideoFramerateNotSupported | TranscodeReason.VideoLevelNotSupported | TranscodeReason.RefFramesNotSupported | TranscodeReason.VideoRangeTypeNotSupported | TranscodeReason.VideoProfileNotSupported;
+        internal const TranscodeReason DirectStreamReasons = AudioReasons | TranscodeReason.ContainerNotSupported | TranscodeReason.VideoCodecTagNotSupported;
 
         private readonly ILogger _logger;
         private readonly ITranscoderSupport _transcoderSupport;
@@ -352,7 +352,7 @@ namespace MediaBrowser.Model.Dlna
                     return TranscodeReason.VideoBitrateNotSupported;
 
                 case ProfileConditionValue.VideoCodecTag:
-                    return TranscodeReason.VideoCodecNotSupported;
+                    return TranscodeReason.VideoCodecTagNotSupported;
 
                 case ProfileConditionValue.VideoFramerate:
                     return TranscodeReason.VideoFramerateNotSupported;
@@ -765,7 +765,19 @@ namespace MediaBrowser.Model.Dlna
                     {
                         var subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, _transcoderSupport, transcodingProfile.Container, transcodingProfile.Protocol);
 
-                        playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
+                        if (options.AlwaysBurnInSubtitleWhenTranscoding && (playlistItem.TranscodeReasons & (VideoReasons | TranscodeReason.ContainerBitrateExceedsLimit)) != 0)
+                        {
+                            playlistItem.SubtitleDeliveryMethod = SubtitleDeliveryMethod.Encode;
+                            foreach (SubtitleProfile profile in options.Profile.SubtitleProfiles)
+                            {
+                                profile.Method = SubtitleDeliveryMethod.Encode;
+                            }
+                        }
+                        else
+                        {
+                            playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
+                        }
+
                         playlistItem.SubtitleFormat = subtitleProfile.Format;
                         playlistItem.SubtitleCodecs = new[] { subtitleProfile.Format };
                     }

+ 3 - 0
MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs

@@ -13,6 +13,7 @@ namespace MediaBrowser.Model.MediaInfo
         {
             EnableDirectPlay = true;
             EnableDirectStream = true;
+            AlwaysBurnInSubtitleWhenTranscoding = false;
             DirectPlayProtocols = new MediaProtocol[] { MediaProtocol.Http };
         }
 
@@ -40,6 +41,8 @@ namespace MediaBrowser.Model.MediaInfo
 
         public bool EnableDirectStream { get; set; }
 
+        public bool AlwaysBurnInSubtitleWhenTranscoding { get; set; }
+
         public IReadOnlyList<MediaProtocol> DirectPlayProtocols { get; set; }
     }
 }

+ 1 - 0
MediaBrowser.Model/Session/TranscodeReason.cs

@@ -18,6 +18,7 @@ namespace MediaBrowser.Model.Session
         // Video Constraints
         VideoProfileNotSupported = 1 << 6,
         VideoRangeTypeNotSupported = 1 << 24,
+        VideoCodecTagNotSupported = 1 << 25,
         VideoLevelNotSupported = 1 << 7,
         VideoResolutionNotSupported = 1 << 8,
         VideoBitDepthNotSupported = 1 << 9,