@ -198,10 +198,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
if ( ! subtitleStream . IsExternal | | subtitleStream . Path . EndsWith ( ".mks" , StringComparison . OrdinalIgnoreCase ) )
{
await ExtractAll Text Subtitles( mediaSource , cancellationToken ) . ConfigureAwait ( false ) ;
await ExtractAll Extractable Subtitles( 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 Get Text SubtitleFormat( MediaStream subtitleStream )
private string Get Extractable SubtitleFormat( 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 ExtractAll Text Subtitles( MediaSourceInfo mediaSource , CancellationToken cancellationToken )
private async Task ExtractAll Extractable Subtitles( 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 { Is Text SubtitleStream: true , SupportsExternalStream : true , IsExternal : false } ) ;
. Where ( stream = > stream is { Is Extractable SubtitleStream: true , SupportsExternalStream : true , IsExternal : false } ) ;
foreach ( var subtitleStream in subtitleStreams )
{
var outputPath = GetSubtitleCachePath ( mediaSource , subtitleStream . Index , "." + Get TextSubtitleFormat ( subtitleStream ) ) ;
var outputPath = GetSubtitleCachePath ( mediaSource , subtitleStream . Index , "." + Get ExtractableSubtitleFileExtension ( subtitleStream ) ) ;
var releaser = await _semaphoreLocks . LockAsync ( outputPath , cancellationToken ) . ConfigureAwait ( false ) ;
@ -483,7 +511,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if ( extractableStreams . Count > 0 )
{
await ExtractAll Text SubtitlesInternal( mediaSource , extractableStreams , cancellationToken ) . ConfigureAwait ( false ) ;
await ExtractAll Extractable SubtitlesInternal( mediaSource , extractableStreams , cancellationToken ) . ConfigureAwait ( false ) ;
}
}
catch ( Exception ex )
@ -496,7 +524,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
private async Task ExtractAll Text SubtitlesInternal(
private async Task ExtractAll Extractable SubtitlesInternal(
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 , "." + Get TextSubtitleFormat ( subtitleStream ) ) ;
var outputPath = GetSubtitleCachePath ( mediaSource , subtitleStream . Index , "." + Get ExtractableSubtitleFileExtension ( subtitleStream ) ) ;
var outputCodec = IsCodecCopyable ( subtitleStream . Codec ) ? "copy" : "srt" ;
var streamIndex = EncodingHelper . FindIndex ( mediaSource . MediaStreams , subtitleStream ) ;