From feb035b9e001374f8830521dbce57539f8fa2f47 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Wed, 27 Jul 2022 10:08:53 +0200 Subject: [PATCH 1/2] Extract external subs from container before determining character set --- .../MediaEncoding/EncodingHelper.cs | 13 ++- .../MediaEncoding/ISubtitleEncoder.cs | 9 +- .../Subtitles/SubtitleEncoder.cs | 87 ++++++++++--------- 3 files changed, 59 insertions(+), 50 deletions(-) diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 1d65f9a345..abb6de4a4b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1145,16 +1145,15 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.SubtitleStream.IsExternal) { - var subtitlePath = state.SubtitleStream.Path; var charsetParam = string.Empty; if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { var charenc = _subtitleEncoder.GetSubtitleFileCharacterSet( - subtitlePath, - state.SubtitleStream.Language, - state.MediaSource.Protocol, - CancellationToken.None).GetAwaiter().GetResult(); + state.SubtitleStream, + state.SubtitleStream.Language, + state.MediaSource, + CancellationToken.None).GetAwaiter().GetResult(); if (!string.IsNullOrEmpty(charenc)) { @@ -1166,7 +1165,7 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Format( CultureInfo.InvariantCulture, "subtitles=f='{0}'{1}{2}{3}{4}{5}", - _mediaEncoder.EscapeSubtitleFilterPath(subtitlePath), + _mediaEncoder.EscapeSubtitleFilterPath(state.SubtitleStream.Path), charsetParam, alphaParam, sub2videoParam, @@ -5529,7 +5528,7 @@ namespace MediaBrowser.Controller.MediaEncoding return index; } - if (string.Equals(currentMediaStream.Path, streamToFind.Path, StringComparison.Ordinal)) + if (string.Equals(currentMediaStream.Path, streamToFind.Path, StringComparison.Ordinal)) { index++; } diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs index 4483cf708a..5bf83a9e31 100644 --- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs @@ -6,7 +6,8 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.MediaEncoding { @@ -37,11 +38,11 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets the subtitle language encoding parameter. /// - /// The path. + /// The subtitle stream. /// The language. - /// The protocol. + /// The media source. /// The cancellation token. /// System.String. - Task GetSubtitleFileCharacterSet(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken); + Task GetSubtitleFileCharacterSet(MediaStream subtitleStream, string language, MediaSourceInfo mediaSource, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 7091af734a..7e42626980 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -238,7 +238,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles // Convert 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); } @@ -351,13 +351,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// /// Converts the text subtitle to SRT. /// - /// The input path. - /// The language. + /// The subtitle stream. /// The input mediaSource. /// The output path. /// The cancellation token. /// Task. - 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); @@ -367,7 +366,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { if (!File.Exists(outputPath)) { - await ConvertTextSubtitleToSrtInternal(inputPath, language, mediaSource, outputPath, cancellationToken).ConfigureAwait(false); + await ConvertTextSubtitleToSrtInternal(subtitleStream, mediaSource, outputPath, cancellationToken).ConfigureAwait(false); } } finally @@ -379,8 +378,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// /// Converts the text subtitle to SRT internal. /// - /// The input path. - /// The language. + /// The subtitle stream. /// The input mediaSource. /// The output path. /// The cancellation token. @@ -388,8 +386,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// /// The inputPath or outputPath is null. /// - 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)) { throw new ArgumentNullException(nameof(inputPath)); @@ -402,7 +401,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles 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 // If we specify character encoding, it rejects with "do not specify a character encoding" and "Unable to recode subtitle event" @@ -420,18 +419,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles int exitCode; using (var process = new Process + { + StartInfo = new ProcessStartInfo { - StartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - FileName = _mediaEncoder.EncoderPath, - Arguments = string.Format(CultureInfo.InvariantCulture, "{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, - EnableRaisingEvents = true - }) + CreateNoWindow = true, + UseShellExecute = false, + FileName = _mediaEncoder.EncoderPath, + Arguments = string.Format(CultureInfo.InvariantCulture, "{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) { _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -580,18 +579,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles int exitCode; using (var process = new Process + { + StartInfo = new ProcessStartInfo { - StartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - FileName = _mediaEncoder.EncoderPath, - Arguments = processArgs, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, - EnableRaisingEvents = true - }) + CreateNoWindow = true, + UseShellExecute = false, + FileName = _mediaEncoder.EncoderPath, + Arguments = processArgs, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) { _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); @@ -729,9 +728,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles } /// - public async Task GetSubtitleFileCharacterSet(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken) + public async Task 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; @@ -754,12 +763,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles switch (protocol) { case MediaProtocol.Http: - { - using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(new Uri(path), cancellationToken) - .ConfigureAwait(false); - return await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - } + { + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(new Uri(path), cancellationToken) + .ConfigureAwait(false); + return await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + } case MediaProtocol.File: return AsyncFile.OpenRead(path); From f49a051a5fa1073ae70f9be1cd3414836647d127 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Tue, 2 Aug 2022 13:21:10 +0200 Subject: [PATCH 2/2] Respect timestamps when extracting subtitles --- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 7e42626980..1148b4042c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -570,7 +570,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles var processArgs = string.Format( 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, subtitleStreamIndex, outputCodec,