diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index f035aebd98..c7ac0184f6 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -385,7 +385,7 @@ namespace MediaBrowser.Api.Playback
Directory.CreateDirectory(parentPath);
}
- var task = MediaEncoder.ConvertTextSubtitleToAss(subtitleStream.Path, path, offset, CancellationToken.None);
+ var task = MediaEncoder.ConvertTextSubtitleToAss(subtitleStream.Path, path, subtitleStream.Language, offset, CancellationToken.None);
Task.WaitAll(task);
}
diff --git a/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs b/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs
index a409dd76cd..31fa78fdb8 100644
--- a/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs
+++ b/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs
@@ -51,10 +51,11 @@ namespace MediaBrowser.Common.MediaInfo
///
/// The input path.
/// The output path.
+ /// The language.
/// The offset.
/// The cancellation token.
/// Task.
- Task ConvertTextSubtitleToAss(string inputPath, string outputPath, TimeSpan offset, CancellationToken cancellationToken);
+ Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, TimeSpan offset, CancellationToken cancellationToken);
///
/// Gets the media info.
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
index d00fbdd1dc..3815549361 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs
@@ -80,7 +80,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The zip client.
/// The app paths.
/// The json serializer.
- public MediaEncoder(ILogger logger, IZipClient zipClient, IApplicationPaths appPaths, IJsonSerializer jsonSerializer)
+ public MediaEncoder(ILogger logger, IZipClient zipClient, IApplicationPaths appPaths,
+ IJsonSerializer jsonSerializer)
{
_logger = logger;
_zipClient = zipClient;
@@ -88,7 +89,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
_jsonSerializer = jsonSerializer;
// Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes
- SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT | ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX);
+ SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT |
+ ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX);
Task.Run(() => VersionedDirectoryPath = GetVersionedDirectoryPath());
}
@@ -123,32 +125,28 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The _ FF MPEG path
///
private string _FFMpegPath;
+
///
/// Gets the path to ffmpeg.exe
///
/// The FF MPEG path.
public string FFMpegPath
{
- get
- {
- return _FFMpegPath ?? (_FFMpegPath = Path.Combine(VersionedDirectoryPath, "ffmpeg.exe"));
- }
+ get { return _FFMpegPath ?? (_FFMpegPath = Path.Combine(VersionedDirectoryPath, "ffmpeg.exe")); }
}
///
/// The _ FF probe path
///
private string _FFProbePath;
+
///
/// Gets the path to ffprobe.exe
///
/// The FF probe path.
private string FFProbePath
{
- get
- {
- return _FFProbePath ?? (_FFProbePath = Path.Combine(VersionedDirectoryPath, "ffprobe.exe"));
- }
+ get { return _FFProbePath ?? (_FFProbePath = Path.Combine(VersionedDirectoryPath, "ffprobe.exe")); }
}
///
@@ -174,9 +172,11 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var resource = assembly.GetManifestResourceNames().First(r => r.StartsWith(srch));
- var filename = resource.Substring(resource.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) + prefix.Length);
+ var filename =
+ resource.Substring(resource.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) + prefix.Length);
- var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true), Path.GetFileNameWithoutExtension(filename));
+ var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true),
+ Path.GetFileNameWithoutExtension(filename));
if (!Directory.Exists(versionedDirectoryPath))
{
@@ -226,7 +226,10 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{
using (var stream = assembly.GetManifestResourceStream(GetType().Namespace + ".fonts." + fontFilename))
{
- using (var fileStream = new FileStream(fontFile, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (
+ var fileStream = new FileStream(fontFile, FileMode.Create, FileAccess.Write, FileShare.Read,
+ StreamDefaults.DefaultFileStreamBufferSize,
+ FileOptions.Asynchronous))
{
await stream.CopyToAsync(fileStream).ConfigureAwait(false);
}
@@ -249,7 +252,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
if (!File.Exists(fontConfigFile))
{
- using (var stream = assembly.GetManifestResourceStream(GetType().Namespace + ".fonts." + fontConfigFilename))
+ using (
+ var stream = assembly.GetManifestResourceStream(GetType().Namespace + ".fonts." + fontConfigFilename)
+ )
{
using (var streamReader = new StreamReader(stream))
{
@@ -259,7 +264,10 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var bytes = Encoding.UTF8.GetBytes(contents);
- using (var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
+ using (
+ var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write,
+ FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize,
+ FileOptions.Asynchronous))
{
await fileStream.WriteAsync(bytes, 0, bytes.Length);
}
@@ -275,9 +283,11 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The type.
/// The cancellation token.
/// Task.
- public Task GetMediaInfo(string[] inputFiles, InputType type, CancellationToken cancellationToken)
+ public Task GetMediaInfo(string[] inputFiles, InputType type,
+ CancellationToken cancellationToken)
{
- return GetMediaInfoInternal(GetInputArgument(inputFiles, type), type != InputType.AudioFile, GetProbeSizeArgument(type), cancellationToken);
+ return GetMediaInfoInternal(GetInputArgument(inputFiles, type), type != InputType.AudioFile,
+ GetProbeSizeArgument(type), cancellationToken);
}
///
@@ -342,27 +352,32 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The cancellation token.
/// Task{MediaInfoResult}.
///
- private async Task GetMediaInfoInternal(string inputPath, bool extractChapters, string probeSizeArgument, CancellationToken cancellationToken)
+ private async Task GetMediaInfoInternal(string inputPath, bool extractChapters,
+ string probeSizeArgument,
+ CancellationToken cancellationToken)
{
var process = new Process
- {
- StartInfo = new ProcessStartInfo
{
- CreateNoWindow = true,
- UseShellExecute = false,
+ StartInfo = new ProcessStartInfo
+ {
+ CreateNoWindow = true,
+ UseShellExecute = false,
- // Must consume both or ffmpeg may hang due to deadlocks. See comments below.
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- FileName = FFProbePath,
- Arguments = string.Format("{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format", probeSizeArgument, inputPath).Trim(),
+ // Must consume both or ffmpeg may hang due to deadlocks. See comments below.
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ FileName = FFProbePath,
+ Arguments =
+ string.Format(
+ "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format",
+ probeSizeArgument, inputPath).Trim(),
- WindowStyle = ProcessWindowStyle.Hidden,
- ErrorDialog = false
- },
+ WindowStyle = ProcessWindowStyle.Hidden,
+ ErrorDialog = false
+ },
- EnableRaisingEvents = true
- };
+ EnableRaisingEvents = true
+ };
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
@@ -501,9 +516,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
if (double.TryParse(subString, NumberStyles.Any, UsCulture, out seconds))
{
lastChapter = new ChapterInfo
- {
- StartPositionTicks = TimeSpan.FromSeconds(seconds).Ticks
- };
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(seconds).Ticks
+ };
chapters.Add(lastChapter);
}
@@ -531,7 +546,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
///
/// The sender.
/// The instance containing the event data.
- void ProcessExited(object sender, EventArgs e)
+ private void ProcessExited(object sender, EventArgs e)
{
((Process)sender).Dispose();
}
@@ -541,6 +556,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
///
/// The input path.
/// The output path.
+ /// The language.
/// The offset.
/// The cancellation token.
/// Task.
@@ -548,7 +564,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// or
/// outputPath
///
- public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, TimeSpan offset, CancellationToken cancellationToken)
+ public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, TimeSpan offset,
+ CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(inputPath))
{
@@ -566,21 +583,26 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var fastSeekParam = fastSeekSeconds > 0 ? "-ss " + fastSeekSeconds + " " : string.Empty;
var slowSeekParam = slowSeekSeconds > 0 ? " -ss " + slowSeekSeconds : string.Empty;
- var process = new Process
- {
- StartInfo = new ProcessStartInfo
- {
- RedirectStandardOutput = false,
- RedirectStandardError = true,
+ var encodingParam = string.IsNullOrEmpty(language) ? string.Empty :
+ GetSubtitleLanguageEncodingParam(language) + " ";
- CreateNoWindow = true,
- UseShellExecute = false,
- FileName = FFMpegPath,
- Arguments = string.Format("{0}-i \"{1}\"{2} \"{3}\"", fastSeekParam, inputPath, slowSeekParam, outputPath),
- WindowStyle = ProcessWindowStyle.Hidden,
- ErrorDialog = false
- }
- };
+ var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ RedirectStandardOutput = false,
+ RedirectStandardError = true,
+
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ FileName = FFMpegPath,
+ Arguments =
+ string.Format("{0}{1}-i \"{2}\"{3} \"{4}\"", encodingParam, fastSeekParam, inputPath, slowSeekParam,
+ outputPath),
+ WindowStyle = ProcessWindowStyle.Hidden,
+ ErrorDialog = false
+ }
+ };
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
@@ -588,7 +610,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt");
- var logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
+ var logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read,
+ StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
try
{
@@ -680,6 +703,24 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
await SetAssFont(outputPath).ConfigureAwait(false);
}
+ ///
+ /// Gets the subtitle language encoding param.
+ ///
+ /// The language.
+ /// System.String.
+ private string GetSubtitleLanguageEncodingParam(string language)
+ {
+ switch (language.ToLower())
+ {
+ case "ara":
+ return "-sub_charenc windows-1256";
+ case "heb":
+ return "-sub_charenc windows-1255";
+ default:
+ return string.Empty;
+ }
+ }
+
///
/// Extracts the text subtitle.
///