|
|
|
@ -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);
|
|
|
|
|
|
|
|
|
|