diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index 5ec333cb16..bb22ca82fa 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -113,6 +113,11 @@ namespace Emby.Server.Implementations.Library
return true;
}
+ if (stream.IsPgsSubtitleStream)
+ {
+ return true;
+ }
+
return false;
}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 16837d98bd..9ecbfa9cf5 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -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);
}
///
- /// Extracts all text subtitles.
+ /// Extracts all extractable subtitles (text and pgs).
///
/// The mediaSource.
/// The cancellation token.
/// Task.
- private async Task ExtractAllTextSubtitles(MediaSourceInfo mediaSource, CancellationToken cancellationToken)
+ private async Task ExtractAllExtractableSubtitles(MediaSourceInfo mediaSource, CancellationToken cancellationToken)
{
var locks = new List();
var extractableStreams = new List();
@@ -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 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);
diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs
index e1082adead..9044c0524e 100644
--- a/MediaBrowser.Model/Entities/MediaStream.cs
+++ b/MediaBrowser.Model/Entities/MediaStream.cs
@@ -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);
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether this is a subtitle steam that is extractable by ffmpeg.
+ /// All text-based and pgs subtitles can be extracted.
+ ///
+ /// true if this is a extractable subtitle steam otherwise, false.
+ public bool IsExtractableSubtitleStream => IsTextSubtitleStream || IsPgsSubtitleStream;
+
///
/// Gets or sets a value indicating whether [supports external stream].
///
@@ -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)