diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index db1d866985..924f010e40 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -158,6 +158,7 @@ public class DynamicHlsController : BaseJellyfinApiController
/// Optional. The max height.
/// Optional. Whether to enable subtitles in the manifest.
/// Optional. Whether to enable Audio Encoding.
+ /// Whether to always burn in subtitles when transcoding.
/// Hls live stream retrieved.
/// A containing the hls file.
[HttpGet("Videos/{itemId}/live.m3u8")]
@@ -216,7 +217,8 @@ public class DynamicHlsController : BaseJellyfinApiController
[FromQuery] int? maxWidth,
[FromQuery] int? maxHeight,
[FromQuery] bool? enableSubtitlesInManifest,
- [FromQuery] bool enableAudioVbrEncoding = true)
+ [FromQuery] bool enableAudioVbrEncoding = true,
+ [FromQuery] bool alwaysBurnInSubtitleWhenTranscoding = false)
{
VideoRequestDto streamingRequest = new VideoRequestDto
{
@@ -251,7 +253,7 @@ public class DynamicHlsController : BaseJellyfinApiController
Height = height,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
- SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
+ SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.External,
MaxRefFrames = maxRefFrames,
MaxVideoBitDepth = maxVideoBitDepth,
RequireAvc = requireAvc ?? false,
@@ -271,7 +273,8 @@ public class DynamicHlsController : BaseJellyfinApiController
MaxHeight = maxHeight,
MaxWidth = maxWidth,
EnableSubtitlesInManifest = enableSubtitlesInManifest ?? true,
- EnableAudioVbrEncoding = enableAudioVbrEncoding
+ EnableAudioVbrEncoding = enableAudioVbrEncoding,
+ AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding
};
// CTS lifecycle is managed internally.
@@ -398,6 +401,7 @@ public class DynamicHlsController : BaseJellyfinApiController
/// Enable adaptive bitrate streaming.
/// Enable trickplay image playlists being added to master playlist.
/// Whether to enable Audio Encoding.
+ /// Whether to always burn in subtitles when transcoding.
/// Video stream returned.
/// A containing the playlist file.
[HttpGet("Videos/{itemId}/master.m3u8")]
@@ -457,7 +461,8 @@ public class DynamicHlsController : BaseJellyfinApiController
[FromQuery] Dictionary streamOptions,
[FromQuery] bool enableAdaptiveBitrateStreaming = true,
[FromQuery] bool enableTrickplay = true,
- [FromQuery] bool enableAudioVbrEncoding = true)
+ [FromQuery] bool enableAudioVbrEncoding = true,
+ [FromQuery] bool alwaysBurnInSubtitleWhenTranscoding = false)
{
var streamingRequest = new HlsVideoRequestDto
{
@@ -493,7 +498,7 @@ public class DynamicHlsController : BaseJellyfinApiController
MaxHeight = maxHeight,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
- SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
+ SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.External,
MaxRefFrames = maxRefFrames,
MaxVideoBitDepth = maxVideoBitDepth,
RequireAvc = requireAvc ?? false,
@@ -512,7 +517,8 @@ public class DynamicHlsController : BaseJellyfinApiController
StreamOptions = streamOptions,
EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming,
EnableTrickplay = enableTrickplay,
- EnableAudioVbrEncoding = enableAudioVbrEncoding
+ EnableAudioVbrEncoding = enableAudioVbrEncoding,
+ AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding
};
return await _dynamicHlsHelper.GetMasterHlsPlaylist(TranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false);
@@ -572,6 +578,7 @@ public class DynamicHlsController : BaseJellyfinApiController
/// Optional. The streaming options.
/// Enable adaptive bitrate streaming.
/// Optional. Whether to enable Audio Encoding.
+ /// Whether to always burn in subtitles when transcoding.
/// Audio stream returned.
/// A containing the playlist file.
[HttpGet("Audio/{itemId}/master.m3u8")]
@@ -629,7 +636,8 @@ public class DynamicHlsController : BaseJellyfinApiController
[FromQuery] EncodingContext? context,
[FromQuery] Dictionary streamOptions,
[FromQuery] bool enableAdaptiveBitrateStreaming = true,
- [FromQuery] bool enableAudioVbrEncoding = true)
+ [FromQuery] bool enableAudioVbrEncoding = true,
+ [FromQuery] bool alwaysBurnInSubtitleWhenTranscoding = false)
{
var streamingRequest = new HlsAudioRequestDto
{
@@ -663,7 +671,7 @@ public class DynamicHlsController : BaseJellyfinApiController
Height = height,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
- SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
+ SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.External,
MaxRefFrames = maxRefFrames,
MaxVideoBitDepth = maxVideoBitDepth,
RequireAvc = requireAvc ?? false,
@@ -681,7 +689,8 @@ public class DynamicHlsController : BaseJellyfinApiController
Context = context ?? EncodingContext.Streaming,
StreamOptions = streamOptions,
EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming,
- EnableAudioVbrEncoding = enableAudioVbrEncoding
+ EnableAudioVbrEncoding = enableAudioVbrEncoding,
+ AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding
};
return await _dynamicHlsHelper.GetMasterHlsPlaylist(TranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false);
@@ -741,6 +750,7 @@ public class DynamicHlsController : BaseJellyfinApiController
/// Optional. The .
/// Optional. The streaming options.
/// Optional. Whether to enable Audio Encoding.
+ /// Whether to always burn in subtitles when transcoding.
/// Video stream returned.
/// A containing the audio file.
[HttpGet("Videos/{itemId}/main.m3u8")]
@@ -797,7 +807,8 @@ public class DynamicHlsController : BaseJellyfinApiController
[FromQuery] int? videoStreamIndex,
[FromQuery] EncodingContext? context,
[FromQuery] Dictionary streamOptions,
- [FromQuery] bool enableAudioVbrEncoding = true)
+ [FromQuery] bool enableAudioVbrEncoding = true,
+ [FromQuery] bool alwaysBurnInSubtitleWhenTranscoding = false)
{
using var cancellationTokenSource = new CancellationTokenSource();
var streamingRequest = new VideoRequestDto
@@ -834,7 +845,7 @@ public class DynamicHlsController : BaseJellyfinApiController
MaxHeight = maxHeight,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
- SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
+ SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.External,
MaxRefFrames = maxRefFrames,
MaxVideoBitDepth = maxVideoBitDepth,
RequireAvc = requireAvc ?? false,
@@ -851,7 +862,8 @@ public class DynamicHlsController : BaseJellyfinApiController
VideoStreamIndex = videoStreamIndex,
Context = context ?? EncodingContext.Streaming,
StreamOptions = streamOptions,
- EnableAudioVbrEncoding = enableAudioVbrEncoding
+ EnableAudioVbrEncoding = enableAudioVbrEncoding,
+ AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding
};
return await GetVariantPlaylistInternal(streamingRequest, cancellationTokenSource)
@@ -911,6 +923,7 @@ public class DynamicHlsController : BaseJellyfinApiController
/// Optional. The .
/// Optional. The streaming options.
/// Optional. Whether to enable Audio Encoding.
+ /// Whether to always burn in subtitles when transcoding.
/// Audio stream returned.
/// A containing the audio file.
[HttpGet("Audio/{itemId}/main.m3u8")]
@@ -966,7 +979,8 @@ public class DynamicHlsController : BaseJellyfinApiController
[FromQuery] int? videoStreamIndex,
[FromQuery] EncodingContext? context,
[FromQuery] Dictionary streamOptions,
- [FromQuery] bool enableAudioVbrEncoding = true)
+ [FromQuery] bool enableAudioVbrEncoding = true,
+ [FromQuery] bool alwaysBurnInSubtitleWhenTranscoding = false)
{
using var cancellationTokenSource = new CancellationTokenSource();
var streamingRequest = new StreamingRequestDto
@@ -1001,7 +1015,7 @@ public class DynamicHlsController : BaseJellyfinApiController
Height = height,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
- SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
+ SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.External,
MaxRefFrames = maxRefFrames,
MaxVideoBitDepth = maxVideoBitDepth,
RequireAvc = requireAvc ?? false,
@@ -1018,7 +1032,8 @@ public class DynamicHlsController : BaseJellyfinApiController
VideoStreamIndex = videoStreamIndex,
Context = context ?? EncodingContext.Streaming,
StreamOptions = streamOptions,
- EnableAudioVbrEncoding = enableAudioVbrEncoding
+ EnableAudioVbrEncoding = enableAudioVbrEncoding,
+ AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding
};
return await GetVariantPlaylistInternal(streamingRequest, cancellationTokenSource)
@@ -1084,6 +1099,7 @@ public class DynamicHlsController : BaseJellyfinApiController
/// Optional. The .
/// Optional. The streaming options.
/// Optional. Whether to enable Audio Encoding.
+ /// Whether to always burn in subtitles when transcoding.
/// Video stream returned.
/// A containing the audio file.
[HttpGet("Videos/{itemId}/hls1/{playlistId}/{segmentId}.{container}")]
@@ -1146,7 +1162,8 @@ public class DynamicHlsController : BaseJellyfinApiController
[FromQuery] int? videoStreamIndex,
[FromQuery] EncodingContext? context,
[FromQuery] Dictionary streamOptions,
- [FromQuery] bool enableAudioVbrEncoding = true)
+ [FromQuery] bool enableAudioVbrEncoding = true,
+ [FromQuery] bool alwaysBurnInSubtitleWhenTranscoding = false)
{
var streamingRequest = new VideoRequestDto
{
@@ -1185,7 +1202,7 @@ public class DynamicHlsController : BaseJellyfinApiController
MaxHeight = maxHeight,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
- SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
+ SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.External,
MaxRefFrames = maxRefFrames,
MaxVideoBitDepth = maxVideoBitDepth,
RequireAvc = requireAvc ?? false,
@@ -1202,7 +1219,8 @@ public class DynamicHlsController : BaseJellyfinApiController
VideoStreamIndex = videoStreamIndex,
Context = context ?? EncodingContext.Streaming,
StreamOptions = streamOptions,
- EnableAudioVbrEncoding = enableAudioVbrEncoding
+ EnableAudioVbrEncoding = enableAudioVbrEncoding,
+ AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding
};
return await GetDynamicSegment(streamingRequest, segmentId)
@@ -1267,6 +1285,7 @@ public class DynamicHlsController : BaseJellyfinApiController
/// Optional. The .
/// Optional. The streaming options.
/// Optional. Whether to enable Audio Encoding.
+ /// Whether to always burn in subtitles when transcoding.
/// Video stream returned.
/// A containing the audio file.
[HttpGet("Audio/{itemId}/hls1/{playlistId}/{segmentId}.{container}")]
@@ -1328,7 +1347,8 @@ public class DynamicHlsController : BaseJellyfinApiController
[FromQuery] int? videoStreamIndex,
[FromQuery] EncodingContext? context,
[FromQuery] Dictionary streamOptions,
- [FromQuery] bool enableAudioVbrEncoding = true)
+ [FromQuery] bool enableAudioVbrEncoding = true,
+ [FromQuery] bool alwaysBurnInSubtitleWhenTranscoding = false)
{
var streamingRequest = new StreamingRequestDto
{
@@ -1365,7 +1385,7 @@ public class DynamicHlsController : BaseJellyfinApiController
Height = height,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
- SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
+ SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.External,
MaxRefFrames = maxRefFrames,
MaxVideoBitDepth = maxVideoBitDepth,
RequireAvc = requireAvc ?? false,
@@ -1382,7 +1402,8 @@ public class DynamicHlsController : BaseJellyfinApiController
VideoStreamIndex = videoStreamIndex,
Context = context ?? EncodingContext.Streaming,
StreamOptions = streamOptions,
- EnableAudioVbrEncoding = enableAudioVbrEncoding
+ EnableAudioVbrEncoding = enableAudioVbrEncoding,
+ AlwaysBurnInSubtitleWhenTranscoding = alwaysBurnInSubtitleWhenTranscoding
};
return await GetDynamicSegment(streamingRequest, segmentId)
diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
index 5050cab418..2d9ecd4f08 100644
--- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs
+++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
@@ -293,6 +293,7 @@ public class MediaInfoHelper
mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
mediaSource.TranscodingContainer = streamInfo.Container;
mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
+ mediaSource.TranscodingUrl += "&alwaysBurnInSubtitleWhenTranscoding=true";
}
else
{
@@ -310,6 +311,11 @@ public class MediaInfoHelper
{
mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
}
+
+ if (streamInfo.AlwaysBurnInSubtitleWhenTranscoding)
+ {
+ mediaSource.TranscodingUrl += "&alwaysBurnInSubtitleWhenTranscoding=true";
+ }
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs
index f77186e25c..20f51ddb71 100644
--- a/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs
+++ b/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs
@@ -193,6 +193,8 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool EnableAudioVbrEncoding { get; set; }
+ public bool AlwaysBurnInSubtitleWhenTranscoding { get; set; }
+
public string GetOption(string qualifier, string name)
{
var value = GetOption(qualifier + "-" + name);
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index d8c4f2f850..f8ba8ddd80 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -941,7 +941,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
// DVBSUB uses the fixed canvas size 720x576
if (state.SubtitleStream is not null
- && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode
+ && ShouldEncodeSubtitle(state)
&& !state.SubtitleStream.IsTextSubtitleStream
&& !string.Equals(state.SubtitleStream.Codec, "DVBSUB", StringComparison.OrdinalIgnoreCase))
{
@@ -1240,7 +1240,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// sub2video for external graphical subtitles
if (state.SubtitleStream is not null
- && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode
+ && ShouldEncodeSubtitle(state)
&& !state.SubtitleStream.IsTextSubtitleStream
&& state.SubtitleStream.IsExternal)
{
@@ -2554,7 +2554,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var isCopyingTimestamps = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive;
- if (state.SubtitleStream is not null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode && !isCopyingTimestamps)
+ if (state.SubtitleStream is not null && state.SubtitleStream.IsTextSubtitleStream && ShouldEncodeSubtitle(state) && !isCopyingTimestamps)
{
var seconds = TimeSpan.FromTicks(state.StartTimeTicks ?? 0).TotalSeconds;
@@ -2755,7 +2755,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.AudioStream.IsExternal)
{
bool hasExternalGraphicsSubs = state.SubtitleStream is not null
- && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode
+ && ShouldEncodeSubtitle(state)
&& state.SubtitleStream.IsExternal
&& !state.SubtitleStream.IsTextSubtitleStream;
int externalAudioMapIndex = hasExternalGraphicsSubs ? 2 : 1;
@@ -3475,7 +3475,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doToneMap = IsSwTonemapAvailable(state, options);
var requireDoviReshaping = doToneMap && state.VideoStream.VideoRangeType == VideoRangeType.DOVI;
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
@@ -3618,7 +3618,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doDeintH2645 = doDeintH264 || doDeintHevc;
var doCuTonemap = IsHwTonemapAvailable(state, options);
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
var hasAssSubs = hasSubs
@@ -3824,7 +3824,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doDeintH2645 = doDeintH264 || doDeintHevc;
var doOclTonemap = IsHwTonemapAvailable(state, options);
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
var hasAssSubs = hasSubs
@@ -4064,7 +4064,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doOclTonemap = !doVppTonemap && IsHwTonemapAvailable(state, options);
var doTonemap = doVppTonemap || doOclTonemap;
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
var hasAssSubs = hasSubs
@@ -4320,7 +4320,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doTonemap = doVaVppTonemap || doOclTonemap;
var doDeintH2645 = doDeintH264 || doDeintHevc;
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
var hasAssSubs = hasSubs
@@ -4636,7 +4636,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doTonemap = doVaVppTonemap || doOclTonemap;
var doDeintH2645 = doDeintH264 || doDeintHevc;
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
var hasAssSubs = hasSubs
@@ -4858,7 +4858,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doVkTonemap = IsVulkanHwTonemapAvailable(state, options);
var doDeintH2645 = doDeintH264 || doDeintHevc;
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
var hasAssSubs = hasSubs
@@ -5091,7 +5091,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doDeintH2645 = doDeintH264 || doDeintHevc;
var doOclTonemap = IsHwTonemapAvailable(state, options);
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
@@ -5339,7 +5339,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var hwScaleFilter = GetHwScaleFilter("scale", "vt", scaleFormat, false, swpInW, swpInH, reqW, reqH, reqMaxW, reqMaxH);
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
var hasAssSubs = hasSubs
@@ -5511,7 +5511,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var doDeintH2645 = doDeintH264 || doDeintHevc;
var doOclTonemap = IsHwTonemapAvailable(state, options);
- var hasSubs = state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream != null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
var hasAssSubs = hasSubs
@@ -5722,7 +5722,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return string.Empty;
}
- var hasSubs = state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasSubs = state.SubtitleStream is not null && ShouldEncodeSubtitle(state);
var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
@@ -7156,7 +7156,7 @@ namespace MediaBrowser.Controller.MediaEncoding
args += keyFrameArg;
- var hasGraphicalSubs = state.SubtitleStream is not null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+ var hasGraphicalSubs = state.SubtitleStream is not null && !state.SubtitleStream.IsTextSubtitleStream && ShouldEncodeSubtitle(state);
var hasCopyTs = false;
@@ -7361,5 +7361,11 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase);
}
+
+ private static bool ShouldEncodeSubtitle(EncodingJobInfo state)
+ {
+ return state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode
+ || (state.BaseRequest.AlwaysBurnInSubtitleWhenTranscoding && !IsCopyCodec(state.OutputVideoCodec));
+ }
}
}
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index bf122dcc7f..6c45f19468 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -639,7 +639,8 @@ namespace MediaBrowser.Model.Dlna
RunTimeTicks = item.RunTimeTicks,
Context = options.Context,
DeviceProfile = options.Profile,
- SubtitleStreamIndex = options.SubtitleStreamIndex ?? GetDefaultSubtitleStreamIndex(item, options.Profile.SubtitleProfiles)
+ SubtitleStreamIndex = options.SubtitleStreamIndex ?? GetDefaultSubtitleStreamIndex(item, options.Profile.SubtitleProfiles),
+ AlwaysBurnInSubtitleWhenTranscoding = options.AlwaysBurnInSubtitleWhenTranscoding
};
var subtitleStream = playlistItem.SubtitleStreamIndex.HasValue ? item.GetMediaStream(MediaStreamType.Subtitle, playlistItem.SubtitleStreamIndex.Value) : null;
@@ -767,20 +768,7 @@ namespace MediaBrowser.Model.Dlna
if (subtitleStream is not null)
{
var subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, _transcoderSupport, transcodingProfile.Container, transcodingProfile.Protocol);
-
- 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.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format;
playlistItem.SubtitleCodecs = [subtitleProfile.Format];
}
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 3be6860880..1ae4e1962d 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -270,6 +270,11 @@ public class StreamInfo
///
public bool EnableAudioVbrEncoding { get; set; }
+ ///
+ /// Gets or sets a value indicating whether always burn in subtitles when transcoding.
+ ///
+ public bool AlwaysBurnInSubtitleWhenTranscoding { get; set; }
+
///
/// Gets a value indicating whether the stream is direct.
///
@@ -953,7 +958,7 @@ public class StreamInfo
list.Add(new NameValuePair("VideoCodec", videoCodecs));
list.Add(new NameValuePair("AudioCodec", audioCodecs));
list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty));
- list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty));
+ list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && (item.AlwaysBurnInSubtitleWhenTranscoding || item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External) ? item.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture) : string.Empty));
list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty));
list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty));
list.Add(new NameValuePair("AudioSampleRate", item.AudioSampleRate.HasValue ? item.AudioSampleRate.Value.ToString(CultureInfo.InvariantCulture) : string.Empty));