Luke Pulverenti 12 роки тому
батько
коміт
27c644e6c8

+ 1 - 1
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);
                 }

+ 2 - 1
MediaBrowser.Common/MediaInfo/IMediaEncoder.cs

@@ -51,10 +51,11 @@ namespace MediaBrowser.Common.MediaInfo
         /// </summary>
         /// <param name="inputPath">The input path.</param>
         /// <param name="outputPath">The output path.</param>
+        /// <param name="language">The language.</param>
         /// <param name="offset">The offset.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        Task ConvertTextSubtitleToAss(string inputPath, string outputPath, TimeSpan offset, CancellationToken cancellationToken);
+        Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, TimeSpan offset, CancellationToken cancellationToken);
 
         /// <summary>
         /// Gets the media info.

+ 92 - 51
MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs

@@ -80,7 +80,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
         /// <param name="zipClient">The zip client.</param>
         /// <param name="appPaths">The app paths.</param>
         /// <param name="jsonSerializer">The json serializer.</param>
-        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
         /// </summary>
         private string _FFMpegPath;
+
         /// <summary>
         /// Gets the path to ffmpeg.exe
         /// </summary>
         /// <value>The FF MPEG path.</value>
         public string FFMpegPath
         {
-            get
-            {
-                return _FFMpegPath ?? (_FFMpegPath = Path.Combine(VersionedDirectoryPath, "ffmpeg.exe"));
-            }
+            get { return _FFMpegPath ?? (_FFMpegPath = Path.Combine(VersionedDirectoryPath, "ffmpeg.exe")); }
         }
 
         /// <summary>
         /// The _ FF probe path
         /// </summary>
         private string _FFProbePath;
+
         /// <summary>
         /// Gets the path to ffprobe.exe
         /// </summary>
         /// <value>The FF probe path.</value>
         private string FFProbePath
         {
-            get
-            {
-                return _FFProbePath ?? (_FFProbePath = Path.Combine(VersionedDirectoryPath, "ffprobe.exe"));
-            }
+            get { return _FFProbePath ?? (_FFProbePath = Path.Combine(VersionedDirectoryPath, "ffprobe.exe")); }
         }
 
         /// <summary>
@@ -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
         /// <param name="type">The type.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        public Task<MediaInfoResult> GetMediaInfo(string[] inputFiles, InputType type, CancellationToken cancellationToken)
+        public Task<MediaInfoResult> 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);
         }
 
         /// <summary>
@@ -342,27 +352,32 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{MediaInfoResult}.</returns>
         /// <exception cref="System.ApplicationException"></exception>
-        private async Task<MediaInfoResult> GetMediaInfoInternal(string inputPath, bool extractChapters, string probeSizeArgument, CancellationToken cancellationToken)
+        private async Task<MediaInfoResult> 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
         /// </summary>
         /// <param name="sender">The sender.</param>
         /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
-        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
         /// </summary>
         /// <param name="inputPath">The input path.</param>
         /// <param name="outputPath">The output path.</param>
+        /// <param name="language">The language.</param>
         /// <param name="offset">The offset.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
@@ -548,7 +564,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
         /// or
         /// outputPath</exception>
         /// <exception cref="System.ApplicationException"></exception>
-        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 encodingParam = string.IsNullOrEmpty(language) ? string.Empty :
+                GetSubtitleLanguageEncodingParam(language) + " ";
+
             var process = new Process
-            {
-                StartInfo = new ProcessStartInfo
                 {
-                    RedirectStandardOutput = false,
-                    RedirectStandardError = true,
-
-                    CreateNoWindow = true,
-                    UseShellExecute = false,
-                    FileName = FFMpegPath,
-                    Arguments = string.Format("{0}-i \"{1}\"{2} \"{3}\"", fastSeekParam, inputPath, slowSeekParam, outputPath),
-                    WindowStyle = ProcessWindowStyle.Hidden,
-                    ErrorDialog = false
-                }
-            };
+                    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);
         }
 
+        /// <summary>
+        /// Gets the subtitle language encoding param.
+        /// </summary>
+        /// <param name="language">The language.</param>
+        /// <returns>System.String.</returns>
+        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;
+            }
+        }
+
         /// <summary>
         /// Extracts the text subtitle.
         /// </summary>