mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
Let HLS Controller decide if subtitle should be burn in
Previously, we predicted whether the subtitle should be burned in with transcode reasons, but that was not accurate because the actual transcoding codec is only determined after the client has requested the stream. This pass through the option to the `DynamicHlsController` to handle the subtitle burn-in during the actual transcoding process. Now the client should be responsible to conditionally load the subtitle when this option is enabled.
This commit is contained in:
parent
9ff7575c85
commit
d944f415f3
@ -158,6 +158,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
/// <param name="maxHeight">Optional. The max height.</param>
|
||||
/// <param name="enableSubtitlesInManifest">Optional. Whether to enable subtitles in the manifest.</param>
|
||||
/// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
|
||||
/// <param name="alwaysBurnInSubtitleWhenTranscoding">Whether to always burn in subtitles when transcoding.</param>
|
||||
/// <response code="200">Hls live stream retrieved.</response>
|
||||
/// <returns>A <see cref="FileResult"/> containing the hls file.</returns>
|
||||
[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
|
||||
/// <param name="enableAdaptiveBitrateStreaming">Enable adaptive bitrate streaming.</param>
|
||||
/// <param name="enableTrickplay">Enable trickplay image playlists being added to master playlist.</param>
|
||||
/// <param name="enableAudioVbrEncoding">Whether to enable Audio Encoding.</param>
|
||||
/// <param name="alwaysBurnInSubtitleWhenTranscoding">Whether to always burn in subtitles when transcoding.</param>
|
||||
/// <response code="200">Video stream returned.</response>
|
||||
/// <returns>A <see cref="FileResult"/> containing the playlist file.</returns>
|
||||
[HttpGet("Videos/{itemId}/master.m3u8")]
|
||||
@ -457,7 +461,8 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
[FromQuery] Dictionary<string, string> 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
|
||||
/// <param name="streamOptions">Optional. The streaming options.</param>
|
||||
/// <param name="enableAdaptiveBitrateStreaming">Enable adaptive bitrate streaming.</param>
|
||||
/// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
|
||||
/// <param name="alwaysBurnInSubtitleWhenTranscoding">Whether to always burn in subtitles when transcoding.</param>
|
||||
/// <response code="200">Audio stream returned.</response>
|
||||
/// <returns>A <see cref="FileResult"/> containing the playlist file.</returns>
|
||||
[HttpGet("Audio/{itemId}/master.m3u8")]
|
||||
@ -629,7 +636,8 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
[FromQuery] EncodingContext? context,
|
||||
[FromQuery] Dictionary<string, string> 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
|
||||
/// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
|
||||
/// <param name="streamOptions">Optional. The streaming options.</param>
|
||||
/// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
|
||||
/// <param name="alwaysBurnInSubtitleWhenTranscoding">Whether to always burn in subtitles when transcoding.</param>
|
||||
/// <response code="200">Video stream returned.</response>
|
||||
/// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
|
||||
[HttpGet("Videos/{itemId}/main.m3u8")]
|
||||
@ -797,7 +807,8 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
[FromQuery] int? videoStreamIndex,
|
||||
[FromQuery] EncodingContext? context,
|
||||
[FromQuery] Dictionary<string, string> 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
|
||||
/// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
|
||||
/// <param name="streamOptions">Optional. The streaming options.</param>
|
||||
/// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
|
||||
/// <param name="alwaysBurnInSubtitleWhenTranscoding">Whether to always burn in subtitles when transcoding.</param>
|
||||
/// <response code="200">Audio stream returned.</response>
|
||||
/// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
|
||||
[HttpGet("Audio/{itemId}/main.m3u8")]
|
||||
@ -966,7 +979,8 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
[FromQuery] int? videoStreamIndex,
|
||||
[FromQuery] EncodingContext? context,
|
||||
[FromQuery] Dictionary<string, string> 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
|
||||
/// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
|
||||
/// <param name="streamOptions">Optional. The streaming options.</param>
|
||||
/// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
|
||||
/// <param name="alwaysBurnInSubtitleWhenTranscoding">Whether to always burn in subtitles when transcoding.</param>
|
||||
/// <response code="200">Video stream returned.</response>
|
||||
/// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
|
||||
[HttpGet("Videos/{itemId}/hls1/{playlistId}/{segmentId}.{container}")]
|
||||
@ -1146,7 +1162,8 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
[FromQuery] int? videoStreamIndex,
|
||||
[FromQuery] EncodingContext? context,
|
||||
[FromQuery] Dictionary<string, string> 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
|
||||
/// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
|
||||
/// <param name="streamOptions">Optional. The streaming options.</param>
|
||||
/// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
|
||||
/// <param name="alwaysBurnInSubtitleWhenTranscoding">Whether to always burn in subtitles when transcoding.</param>
|
||||
/// <response code="200">Video stream returned.</response>
|
||||
/// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
|
||||
[HttpGet("Audio/{itemId}/hls1/{playlistId}/{segmentId}.{container}")]
|
||||
@ -1328,7 +1347,8 @@ public class DynamicHlsController : BaseJellyfinApiController
|
||||
[FromQuery] int? videoStreamIndex,
|
||||
[FromQuery] EncodingContext? context,
|
||||
[FromQuery] Dictionary<string, string> 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)
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -270,6 +270,11 @@ public class StreamInfo
|
||||
/// </summary>
|
||||
public bool EnableAudioVbrEncoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether always burn in subtitles when transcoding.
|
||||
/// </summary>
|
||||
public bool AlwaysBurnInSubtitleWhenTranscoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the stream is direct.
|
||||
/// </summary>
|
||||
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user