mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-05-24 02:02:29 -04:00
Allow streaming of raw PGS subtitles without transcoding (#12056)
This commit is contained in:
parent
3262f8dc2a
commit
fc1bee30a6
@ -113,6 +113,11 @@ namespace Emby.Server.Implementations.Library
|
||||
return true;
|
||||
}
|
||||
|
||||
if (stream.IsPgsSubtitleStream)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -198,10 +198,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
{
|
||||
if (!subtitleStream.IsExternal || subtitleStream.Path.EndsWith(".mks", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await ExtractAllTextSubtitles(mediaSource, cancellationToken).ConfigureAwait(false);
|
||||
await ExtractAllExtractableSubtitles(mediaSource, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var outputFormat = GetTextSubtitleFormat(subtitleStream);
|
||||
var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + outputFormat);
|
||||
var outputFileExtension = GetExtractableSubtitleFileExtension(subtitleStream);
|
||||
var outputFormat = GetExtractableSubtitleFormat(subtitleStream);
|
||||
var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + outputFileExtension);
|
||||
|
||||
return new SubtitleInfo()
|
||||
{
|
||||
@ -215,6 +216,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
var currentFormat = (Path.GetExtension(subtitleStream.Path) ?? subtitleStream.Codec)
|
||||
.TrimStart('.');
|
||||
|
||||
// Handle PGS subtitles as raw streams for the client to render
|
||||
if (MediaStream.IsPgsFormat(currentFormat))
|
||||
{
|
||||
return new SubtitleInfo()
|
||||
{
|
||||
Path = subtitleStream.Path,
|
||||
Protocol = _mediaSourceManager.GetPathProtocol(subtitleStream.Path),
|
||||
Format = "pgssub",
|
||||
IsExternal = true
|
||||
};
|
||||
}
|
||||
|
||||
// Fallback to ffmpeg conversion
|
||||
if (!_subtitleParser.SupportsFileExtension(currentFormat))
|
||||
{
|
||||
@ -428,10 +441,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
_logger.LogInformation("ffmpeg subtitle conversion succeeded for {Path}", inputPath);
|
||||
}
|
||||
|
||||
private string GetTextSubtitleFormat(MediaStream subtitleStream)
|
||||
private string GetExtractableSubtitleFormat(MediaStream subtitleStream)
|
||||
{
|
||||
if (string.Equals(subtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(subtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase))
|
||||
|| string.Equals(subtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(subtitleStream.Codec, "pgssub", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return subtitleStream.Codec;
|
||||
}
|
||||
@ -441,21 +455,35 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
}
|
||||
}
|
||||
|
||||
private string GetExtractableSubtitleFileExtension(MediaStream subtitleStream)
|
||||
{
|
||||
// Using .pgssub as file extension is not allowed by ffmpeg. The file extension for pgs subtitles is .sup.
|
||||
if (string.Equals(subtitleStream.Codec, "pgssub", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "sup";
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetExtractableSubtitleFormat(subtitleStream);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsCodecCopyable(string codec)
|
||||
{
|
||||
return string.Equals(codec, "ass", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "ssa", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "srt", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "subrip", StringComparison.OrdinalIgnoreCase);
|
||||
|| string.Equals(codec, "subrip", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "pgssub", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts all text subtitles.
|
||||
/// Extracts all extractable subtitles (text and pgs).
|
||||
/// </summary>
|
||||
/// <param name="mediaSource">The mediaSource.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private async Task ExtractAllTextSubtitles(MediaSourceInfo mediaSource, CancellationToken cancellationToken)
|
||||
private async Task ExtractAllExtractableSubtitles(MediaSourceInfo mediaSource, CancellationToken cancellationToken)
|
||||
{
|
||||
var locks = new List<IDisposable>();
|
||||
var extractableStreams = new List<MediaStream>();
|
||||
@ -463,11 +491,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
try
|
||||
{
|
||||
var subtitleStreams = mediaSource.MediaStreams
|
||||
.Where(stream => stream is { IsTextSubtitleStream: true, SupportsExternalStream: true, IsExternal: false });
|
||||
.Where(stream => stream is { IsExtractableSubtitleStream: true, SupportsExternalStream: true, IsExternal: false });
|
||||
|
||||
foreach (var subtitleStream in subtitleStreams)
|
||||
{
|
||||
var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + GetTextSubtitleFormat(subtitleStream));
|
||||
var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + GetExtractableSubtitleFileExtension(subtitleStream));
|
||||
|
||||
var releaser = await _semaphoreLocks.LockAsync(outputPath, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@ -483,7 +511,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
|
||||
if (extractableStreams.Count > 0)
|
||||
{
|
||||
await ExtractAllTextSubtitlesInternal(mediaSource, extractableStreams, cancellationToken).ConfigureAwait(false);
|
||||
await ExtractAllExtractableSubtitlesInternal(mediaSource, extractableStreams, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -496,7 +524,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExtractAllTextSubtitlesInternal(
|
||||
private async Task ExtractAllExtractableSubtitlesInternal(
|
||||
MediaSourceInfo mediaSource,
|
||||
List<MediaStream> subtitleStreams,
|
||||
CancellationToken cancellationToken)
|
||||
@ -510,7 +538,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
|
||||
foreach (var subtitleStream in subtitleStreams)
|
||||
{
|
||||
var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + GetTextSubtitleFormat(subtitleStream));
|
||||
var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + GetExtractableSubtitleFileExtension(subtitleStream));
|
||||
var outputCodec = IsCodecCopyable(subtitleStream.Codec) ? "copy" : "srt";
|
||||
var streamIndex = EncodingHelper.FindIndex(mediaSource.MediaStreams, subtitleStream);
|
||||
|
||||
|
@ -585,6 +585,31 @@ namespace MediaBrowser.Model.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPgsSubtitleStream
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Type != MediaStreamType.Subtitle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(Codec) && !IsExternal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsPgsFormat(Codec);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this is a subtitle steam that is extractable by ffmpeg.
|
||||
/// All text-based and pgs subtitles can be extracted.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this is a extractable subtitle steam otherwise, <c>false</c>.</value>
|
||||
public bool IsExtractableSubtitleStream => IsTextSubtitleStream || IsPgsSubtitleStream;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [supports external stream].
|
||||
/// </summary>
|
||||
@ -666,6 +691,14 @@ namespace MediaBrowser.Model.Entities
|
||||
&& !string.Equals(codec, "sub", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public static bool IsPgsFormat(string format)
|
||||
{
|
||||
string codec = format ?? string.Empty;
|
||||
|
||||
return codec.Contains("pgs", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(codec, "sup", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public bool SupportsSubtitleConversionTo(string toCodec)
|
||||
{
|
||||
if (!IsTextSubtitleStream)
|
||||
|
Loading…
x
Reference in New Issue
Block a user