@ -241,7 +241,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
// Convert
// Convert
var outputPath = GetSubtitleCachePath ( mediaSource , subtitleStream . Index , ".srt" ) ;
var outputPath = GetSubtitleCachePath ( mediaSource , subtitleStream . Index , ".srt" ) ;
await ConvertTextSubtitleToSrt ( subtitleStream .Path , subtitleStream . Language , mediaSource , outputPath , cancellationToken ) . ConfigureAwait ( false ) ;
await ConvertTextSubtitleToSrt ( subtitleStream , mediaSource , outputPath , cancellationToken ) . ConfigureAwait ( false ) ;
return new SubtitleInfo ( outputPath , MediaProtocol . File , "srt" , true ) ;
return new SubtitleInfo ( outputPath , MediaProtocol . File , "srt" , true ) ;
}
}
@ -320,13 +320,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// <summary>
/// <summary>
/// Converts the text subtitle to SRT.
/// Converts the text subtitle to SRT.
/// </summary>
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="subtitleStream">The subtitle stream.</param>
/// <param name="language">The language.</param>
/// <param name="mediaSource">The input mediaSource.</param>
/// <param name="mediaSource">The input mediaSource.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <returns>Task.</returns>
private async Task ConvertTextSubtitleToSrt ( string inputPath , string language , MediaSourceInfo mediaSource , string outputPath , CancellationToken cancellationToken )
private async Task ConvertTextSubtitleToSrt ( MediaStream subtitleStream , MediaSourceInfo mediaSource , string outputPath , CancellationToken cancellationToken )
{
{
var semaphore = GetLock ( outputPath ) ;
var semaphore = GetLock ( outputPath ) ;
@ -336,7 +335,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
{
if ( ! File . Exists ( outputPath ) )
if ( ! File . Exists ( outputPath ) )
{
{
await ConvertTextSubtitleToSrtInternal ( inputPath, language , mediaSource , outputPath , cancellationToken ) . ConfigureAwait ( false ) ;
await ConvertTextSubtitleToSrtInternal ( subtitleStream , mediaSource , outputPath , cancellationToken ) . ConfigureAwait ( false ) ;
}
}
}
}
finally
finally
@ -348,8 +347,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// <summary>
/// <summary>
/// Converts the text subtitle to SRT internal.
/// Converts the text subtitle to SRT internal.
/// </summary>
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="subtitleStream">The subtitle stream.</param>
/// <param name="language">The language.</param>
/// <param name="mediaSource">The input mediaSource.</param>
/// <param name="mediaSource">The input mediaSource.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="cancellationToken">The cancellation token.</param>
@ -357,8 +355,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// <exception cref="ArgumentNullException">
/// <exception cref="ArgumentNullException">
/// The <c>inputPath</c> or <c>outputPath</c> is <c>null</c>.
/// The <c>inputPath</c> or <c>outputPath</c> is <c>null</c>.
/// </exception>
/// </exception>
private async Task ConvertTextSubtitleToSrtInternal ( string inputPath , string language , MediaSourceInfo mediaSource , string outputPath , CancellationToken cancellationToken )
private async Task ConvertTextSubtitleToSrtInternal ( MediaStream subtitleStream , MediaSourceInfo mediaSource , string outputPath , CancellationToken cancellationToken )
{
{
var inputPath = subtitleStream . Path ;
if ( string . IsNullOrEmpty ( inputPath ) )
if ( string . IsNullOrEmpty ( inputPath ) )
{
{
throw new ArgumentNullException ( nameof ( inputPath ) ) ;
throw new ArgumentNullException ( nameof ( inputPath ) ) ;
@ -371,7 +370,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
Directory . CreateDirectory ( Path . GetDirectoryName ( outputPath ) ? ? throw new ArgumentException ( $"Provided path ({outputPath}) is not valid." , nameof ( outputPath ) ) ) ;
Directory . CreateDirectory ( Path . GetDirectoryName ( outputPath ) ? ? throw new ArgumentException ( $"Provided path ({outputPath}) is not valid." , nameof ( outputPath ) ) ) ;
var encodingParam = await GetSubtitleFileCharacterSet ( inputPath, language , mediaSource . Protocol , cancellationToken ) . ConfigureAwait ( false ) ;
var encodingParam = await GetSubtitleFileCharacterSet ( subtitleStream, subtitleStream . Language , mediaSource , cancellationToken ) . ConfigureAwait ( false ) ;
// FFmpeg automatically convert character encoding when it is UTF-16
// FFmpeg automatically convert character encoding when it is UTF-16
// If we specify character encoding, it rejects with "do not specify a character encoding" and "Unable to recode subtitle event"
// If we specify character encoding, it rejects with "do not specify a character encoding" and "Unable to recode subtitle event"
@ -389,18 +388,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles
int exitCode ;
int exitCode ;
using ( var process = new Process
using ( var process = new Process
{
StartInfo = new ProcessStartInfo
{
{
StartInfo = new ProcessStartInfo
CreateNoWindow = true ,
{
UseShellExecute = false ,
CreateNoWindow = true ,
FileName = _mediaEncoder . EncoderPath ,
UseShellExecute = false ,
Arguments = string . Format ( CultureInfo . InvariantCulture , "{0} -i \"{1}\" -c:s srt \"{2}\"" , encodingParam , inputPath , outputPath ) ,
FileName = _mediaEncoder . EncoderPath ,
WindowStyle = ProcessWindowStyle . Hidden ,
Arguments = string . Format ( CultureInfo . InvariantCulture , "{0} -i \"{1}\" -c:s srt \"{2}\"" , encodingParam , inputPath , outputPath ) ,
ErrorDialog = false
WindowStyle = ProcessWindowStyle . Hidden ,
} ,
ErrorDialog = false
EnableRaisingEvents = true
} ,
} )
EnableRaisingEvents = true
} )
{
{
_logger . LogInformation ( "{0} {1}" , process . StartInfo . FileName , process . StartInfo . Arguments ) ;
_logger . LogInformation ( "{0} {1}" , process . StartInfo . FileName , process . StartInfo . Arguments ) ;
@ -540,7 +539,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var processArgs = string . Format (
var processArgs = string . Format (
CultureInfo . InvariantCulture ,
CultureInfo . InvariantCulture ,
"-i {0} - map 0:{1} -an -vn -c:s {2} \"{3}\"",
"-i {0} - copyts - map 0:{1} -an -vn -c:s {2} \"{3}\"",
inputPath ,
inputPath ,
subtitleStreamIndex ,
subtitleStreamIndex ,
outputCodec ,
outputCodec ,
@ -549,18 +548,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles
int exitCode ;
int exitCode ;
using ( var process = new Process
using ( var process = new Process
{
StartInfo = new ProcessStartInfo
{
{
StartInfo = new ProcessStartInfo
CreateNoWindow = true ,
{
UseShellExecute = false ,
CreateNoWindow = true ,
FileName = _mediaEncoder . EncoderPath ,
UseShellExecute = false ,
Arguments = processArgs ,
FileName = _mediaEncoder . EncoderPath ,
WindowStyle = ProcessWindowStyle . Hidden ,
Arguments = processArgs ,
ErrorDialog = false
WindowStyle = ProcessWindowStyle . Hidden ,
} ,
ErrorDialog = false
EnableRaisingEvents = true
} ,
} )
EnableRaisingEvents = true
} )
{
{
_logger . LogInformation ( "{File} {Arguments}" , process . StartInfo . FileName , process . StartInfo . Arguments ) ;
_logger . LogInformation ( "{File} {Arguments}" , process . StartInfo . FileName , process . StartInfo . Arguments ) ;
@ -698,9 +697,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
/// <inheritdoc />
/// <inheritdoc />
public async Task < string > GetSubtitleFileCharacterSet ( string path , string language , MediaProtocol protocol , CancellationToken cancellationToken )
public async Task < string > GetSubtitleFileCharacterSet ( MediaStream subtitleStream , string language , MediaSourceInfo mediaSource , CancellationToken cancellationToken )
{
{
using ( var stream = await GetStream ( path , protocol , cancellationToken ) . ConfigureAwait ( false ) )
var subtitleCodec = subtitleStream . Codec ;
var path = subtitleStream . Path ;
if ( path . EndsWith ( ".mks" , StringComparison . OrdinalIgnoreCase ) )
{
path = GetSubtitleCachePath ( mediaSource , subtitleStream . Index , "." + subtitleCodec ) ;
await ExtractTextSubtitle ( mediaSource , subtitleStream , subtitleCodec , path , cancellationToken )
. ConfigureAwait ( false ) ;
}
using ( var stream = await GetStream ( path , mediaSource . Protocol , cancellationToken ) . ConfigureAwait ( false ) )
{
{
var charset = CharsetDetector . DetectFromStream ( stream ) . Detected ? . EncodingName ? ? string . Empty ;
var charset = CharsetDetector . DetectFromStream ( stream ) . Detected ? . EncodingName ? ? string . Empty ;
@ -723,12 +732,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles
switch ( protocol )
switch ( protocol )
{
{
case MediaProtocol . Http :
case MediaProtocol . Http :
{
{
using var response = await _httpClientFactory . CreateClient ( NamedClient . Default )
using var response = await _httpClientFactory . CreateClient ( NamedClient . Default )
. GetAsync ( new Uri ( path ) , cancellationToken )
. GetAsync ( new Uri ( path ) , cancellationToken )
. ConfigureAwait ( false ) ;
. ConfigureAwait ( false ) ;
return await response . Content . ReadAsStreamAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
return await response . Content . ReadAsStreamAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
}
}
case MediaProtocol . File :
case MediaProtocol . File :
return AsyncFile . OpenRead ( path ) ;
return AsyncFile . OpenRead ( path ) ;