diff options
Diffstat (limited to 'MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs')
| -rw-r--r-- | MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 190 |
1 files changed, 54 insertions, 136 deletions
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 6dda49a55..0bbc2d916 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -17,9 +17,9 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; -using CommonIO; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Diagnostics; +using MediaBrowser.Model.Text; using UniversalDetector; namespace MediaBrowser.MediaEncoding.Subtitles @@ -34,9 +34,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IJsonSerializer _json; private readonly IHttpClient _httpClient; private readonly IMediaSourceManager _mediaSourceManager; - private readonly IMemoryStreamProvider _memoryStreamProvider; + private readonly IMemoryStreamFactory _memoryStreamProvider; + private readonly IProcessFactory _processFactory; + private readonly ITextEncoding _textEncoding; - public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IMemoryStreamProvider memoryStreamProvider) + public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IMemoryStreamFactory memoryStreamProvider, IProcessFactory processFactory, ITextEncoding textEncoding) { _libraryManager = libraryManager; _logger = logger; @@ -47,6 +49,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles _httpClient = httpClient; _mediaSourceManager = mediaSourceManager; _memoryStreamProvider = memoryStreamProvider; + _processFactory = processFactory; + _textEncoding = textEncoding; } private string SubtitleCachePath @@ -137,8 +141,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles .ConfigureAwait(false); var inputFormat = subtitle.Item2; + var writer = TryGetWriter(outputFormat); - if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null) + if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && writer == null) + { + return subtitle.Item1; + } + + if (writer == null) { return subtitle.Item1; } @@ -417,7 +427,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// or /// outputPath /// </exception> - /// <exception cref="System.ApplicationException"></exception> private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) @@ -439,46 +448,29 @@ namespace MediaBrowser.MediaEncoding.Subtitles encodingParam = " -sub_charenc " + encodingParam; } - var process = new Process + var process = _processFactory.Create(new ProcessOptions { - StartInfo = new ProcessStartInfo - { - RedirectStandardOutput = false, - RedirectStandardError = true, - RedirectStandardInput = true, - - CreateNoWindow = true, - UseShellExecute = false, - FileName = _mediaEncoder.EncoderPath, - Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), + CreateNoWindow = true, + UseShellExecute = false, + FileName = _mediaEncoder.EncoderPath, + Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - } - }; + IsHidden = true, + ErrorDialog = false + }); _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); - - var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, - true); - try { process.Start(); } catch (Exception ex) { - logFileStream.Dispose(); - _logger.ErrorException("Error starting ffmpeg", ex); throw; } - - var logTask = process.StandardError.BaseStream.CopyToAsync(logFileStream); var ranToCompletion = process.WaitForExit(60000); @@ -488,19 +480,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { _logger.Info("Killing ffmpeg subtitle conversion process"); - process.StandardInput.WriteLine("q"); - process.WaitForExit(1000); - - await logTask.ConfigureAwait(false); + process.Kill(); } catch (Exception ex) { _logger.ErrorException("Error killing subtitle conversion process", ex); } - finally - { - logFileStream.Dispose(); - } } var exitCode = ranToCompletion ? process.ExitCode : -1; @@ -533,13 +518,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (failed) { - var msg = string.Format("ffmpeg subtitle converted failed for {0}", inputPath); + var msg = string.Format("ffmpeg subtitle conversion failed for {0}", inputPath); _logger.Error(msg); - throw new ApplicationException(msg); + throw new Exception(msg); } await SetAssFont(outputPath).ConfigureAwait(false); + + _logger.Info("ffmpeg subtitle conversion succeeded for {0}", inputPath); } /// <summary> @@ -592,48 +579,30 @@ namespace MediaBrowser.MediaEncoding.Subtitles var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath, subtitleStreamIndex, outputCodec, outputPath); - var process = new Process + var process = _processFactory.Create(new ProcessOptions { - StartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - - RedirectStandardOutput = false, - RedirectStandardError = true, - RedirectStandardInput = true, + CreateNoWindow = true, + UseShellExecute = false, - FileName = _mediaEncoder.EncoderPath, - Arguments = processArgs, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - } - }; + FileName = _mediaEncoder.EncoderPath, + Arguments = processArgs, + IsHidden = true, + ErrorDialog = false + }); _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-extract-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); - - var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, - true); - try { process.Start(); } catch (Exception ex) { - logFileStream.Dispose(); - _logger.ErrorException("Error starting ffmpeg", ex); throw; } - // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - Task.Run(() => StartStreamingLog(process.StandardError.BaseStream, logFileStream)); - var ranToCompletion = process.WaitForExit(300000); if (!ranToCompletion) @@ -642,17 +611,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { _logger.Info("Killing ffmpeg subtitle extraction process"); - process.StandardInput.WriteLine("q"); - process.WaitForExit(1000); + process.Kill(); } catch (Exception ex) { _logger.ErrorException("Error killing subtitle extraction process", ex); } - finally - { - logFileStream.Dispose(); - } } var exitCode = ranToCompletion ? process.ExitCode : -1; @@ -674,10 +638,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles { } - catch (DirectoryNotFoundException) - { - - } catch (IOException ex) { _logger.ErrorException("Error deleting extracted subtitle {0}", ex, outputPath); @@ -694,7 +654,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.Error(msg); - throw new ApplicationException(msg); + throw new Exception(msg); } else { @@ -709,33 +669,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - private async Task StartStreamingLog(Stream source, Stream target) - { - try - { - using (var reader = new StreamReader(source)) - { - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - - var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); - - await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - await target.FlushAsync().ConfigureAwait(false); - } - } - } - catch (ObjectDisposedException) - { - // Don't spam the log. This doesn't seem to throw in windows, but sometimes under linux - } - catch (Exception ex) - { - _logger.ErrorException("Error reading ffmpeg log", ex); - } - } - /// <summary> /// Sets the ass font. /// </summary> @@ -748,20 +681,26 @@ namespace MediaBrowser.MediaEncoding.Subtitles string text; Encoding encoding; - using (var reader = new StreamReader(file, true)) + using (var fileStream = _fileSystem.OpenRead(file)) { - encoding = reader.CurrentEncoding; + using (var reader = new StreamReader(fileStream, true)) + { + encoding = reader.CurrentEncoding; - text = await reader.ReadToEndAsync().ConfigureAwait(false); + text = await reader.ReadToEndAsync().ConfigureAwait(false); + } } var newText = text.Replace(",Arial,", ",Arial Unicode MS,"); if (!string.Equals(text, newText)) { - using (var writer = new StreamWriter(file, false, encoding)) + using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) { - writer.Write(newText); + using (var writer = new StreamWriter(fileStream, encoding)) + { + writer.Write(newText); + } } } } @@ -794,7 +733,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles { if (protocol == MediaProtocol.File) { - if (GetFileEncoding(path).Equals(Encoding.UTF8)) + var fileEncoding = _textEncoding.GetFileEncoding(path); + + if (fileEncoding != null && fileEncoding.Equals(Encoding.UTF8)) { return string.Empty; } @@ -901,29 +842,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles return null; } - private Encoding GetFileEncoding(string srcFile) - { - // *** Detect byte order mark if any - otherwise assume default - var buffer = new byte[5]; - - using (var file = _fileSystem.GetFileStream(srcFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { - file.Read(buffer, 0, 5); - } - - if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf) - return Encoding.UTF8; - if (buffer[0] == 0xfe && buffer[1] == 0xff) - return Encoding.Unicode; - if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff) - return Encoding.UTF32; - if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76) - return Encoding.UTF7; - - // It's ok - anything aside from utf is ok since that's what we're looking for - return Encoding.Default; - } - private async Task<Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken) { if (protocol == MediaProtocol.Http) @@ -932,7 +850,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } if (protocol == MediaProtocol.File) { - return _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + return _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite); } throw new ArgumentOutOfRangeException("protocol"); |
