From 997816443862a8db68f314a6d23ef076c9661c01 Mon Sep 17 00:00:00 2001 From: Jonas Resch Date: Mon, 22 Nov 2021 21:47:52 +0100 Subject: Add support for external audio files --- .../MediaEncoding/EncodingHelper.cs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 5715194b8..5326ecd20 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -678,6 +678,12 @@ namespace MediaBrowser.Controller.MediaEncoding arg.Append("-i ") .Append(GetInputPathArgument(state)); + if (state.AudioStream.IsExternal) + { + arg.Append(" -i ") + .Append(string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", state.AudioStream.Path)); + } + if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream) @@ -1999,10 +2005,17 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.AudioStream != null) { - args += string.Format( - CultureInfo.InvariantCulture, - " -map 0:{0}", - state.AudioStream.Index); + if (state.AudioStream.IsExternal) + { + args += " -map 1:a"; + } + else + { + args += string.Format( + CultureInfo.InvariantCulture, + " -map 0:{0}", + state.AudioStream.Index); + } } else { -- cgit v1.2.3 From a68e58556c49ee9bc1c27fac696ffc9170c95e84 Mon Sep 17 00:00:00 2001 From: Jonas Resch Date: Sat, 27 Nov 2021 12:10:57 +0100 Subject: Implement code feedback - Rewrite AudioResolver - Use async & await instead of .Result - Add support for audio containers with multiple audio streams (e.g. mka) - Fix bug when using external subtitle and external audio streams at the same time --- .../MediaEncoding/EncodingHelper.cs | 21 +- MediaBrowser.Providers/MediaInfo/AudioResolver.cs | 271 ++++++--------------- .../MediaInfo/FFProbeProvider.cs | 16 +- .../MediaInfo/FFProbeVideoInfo.cs | 16 +- 4 files changed, 114 insertions(+), 210 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 5326ecd20..5695ee2db 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -678,12 +678,6 @@ namespace MediaBrowser.Controller.MediaEncoding arg.Append("-i ") .Append(GetInputPathArgument(state)); - if (state.AudioStream.IsExternal) - { - arg.Append(" -i ") - .Append(string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", state.AudioStream.Path)); - } - if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream) @@ -702,6 +696,12 @@ namespace MediaBrowser.Controller.MediaEncoding arg.Append(" -i \"").Append(subtitlePath).Append('\"'); } + if (state.AudioStream != null && state.AudioStream.IsExternal) + { + arg.Append(" -i ") + .Append(string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", state.AudioStream.Path)); + } + return arg.ToString(); } @@ -2007,7 +2007,14 @@ namespace MediaBrowser.Controller.MediaEncoding { if (state.AudioStream.IsExternal) { - args += " -map 1:a"; + int externalAudioMapIndex = state.SubtitleStream != null && state.SubtitleStream.IsExternal ? 2 : 1; + int externalAudioStream = state.MediaSource.MediaStreams.Where(i => i.Path == state.AudioStream.Path).ToList().IndexOf(state.AudioStream); + + args += string.Format( + CultureInfo.InvariantCulture, + " -map {0}:{1}", + externalAudioMapIndex, + externalAudioStream); } else { diff --git a/MediaBrowser.Providers/MediaInfo/AudioResolver.cs b/MediaBrowser.Providers/MediaInfo/AudioResolver.cs index fce2fa551..8d5f8d86e 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioResolver.cs @@ -1,13 +1,13 @@ -#nullable disable - #pragma warning disable CA1002, CS1591 using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; +using Emby.Naming.Audio; +using Emby.Naming.Common; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Providers; @@ -21,24 +21,15 @@ namespace MediaBrowser.Providers.MediaInfo { public class AudioResolver { - private readonly ILocalizationManager _localization; - - private readonly IMediaEncoder _mediaEncoder; - - private readonly CancellationToken _cancellationToken; - - public AudioResolver(ILocalizationManager localization, IMediaEncoder mediaEncoder, CancellationToken cancellationToken = default) - { - _localization = localization; - _mediaEncoder = mediaEncoder; - _cancellationToken = cancellationToken; - } - - public List GetExternalAudioStreams( + public async Task> GetExternalAudioStreams( Video video, int startIndex, IDirectoryService directoryService, - bool clearCache) + NamingOptions namingOptions, + bool clearCache, + ILocalizationManager localizationManager, + IMediaEncoder mediaEncoder, + CancellationToken cancellationToken) { var streams = new List(); @@ -47,198 +38,117 @@ namespace MediaBrowser.Providers.MediaInfo return streams; } - AddExternalAudioStreams(streams, video.ContainingFolderPath, video.Path, startIndex, directoryService, clearCache); - - startIndex += streams.Count; + List paths = GetExternalAudioFiles(video, directoryService, namingOptions, clearCache); - string folder = video.GetInternalMetadataPath(); - - if (!Directory.Exists(folder)) - { - return streams; - } - - try - { - AddExternalAudioStreams(streams, folder, video.Path, startIndex, directoryService, clearCache); - } - catch (IOException) - { - } + await AddExternalAudioStreams(streams, paths, startIndex, localizationManager, mediaEncoder, cancellationToken); return streams; } - public IEnumerable GetExternalAudioFiles( + public List GetExternalAudioFiles( Video video, IDirectoryService directoryService, + NamingOptions namingOptions, bool clearCache) { + List paths = new List(); + if (!video.IsFileProtocol) { - yield break; + return paths; } - var streams = GetExternalAudioStreams(video, 0, directoryService, clearCache); + paths.AddRange(GetAudioFilesFromFolder(video.ContainingFolderPath, video.Path, directoryService, namingOptions, clearCache)); + paths.AddRange(GetAudioFilesFromFolder(video.GetInternalMetadataPath(), video.Path, directoryService, namingOptions, clearCache)); - foreach (var stream in streams) - { - yield return stream.Path; - } + return paths; } - public void AddExternalAudioStreams( - List streams, - string videoPath, - int startIndex, - IReadOnlyList files) + private List GetAudioFilesFromFolder( + string folder, + string videoFileName, + IDirectoryService directoryService, + NamingOptions namingOptions, + bool clearCache) { - var videoFileNameWithoutExtension = NormalizeFilenameForAudioComparison(videoPath); + List paths = new List(); + string videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(videoFileName); - for (var i = 0; i < files.Count; i++) + if (!Directory.Exists(folder)) + { + return paths; + } + + var files = directoryService.GetFilePaths(folder, clearCache, true); + for (int i = 0; i < files.Count; i++) { + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(files[i]); - var fullName = files[i]; - var extension = Path.GetExtension(fullName.AsSpan()); - if (!IsAudioExtension(extension)) + if (!AudioFileParser.IsAudioFile(files[i], namingOptions)) { continue; } - Model.MediaInfo.MediaInfo mediaInfo = GetMediaInfo(fullName).Result; - MediaStream mediaStream = mediaInfo.MediaStreams.First(); - mediaStream.Index = startIndex++; - mediaStream.Type = MediaStreamType.Audio; - mediaStream.IsExternal = true; - mediaStream.Path = fullName; - mediaStream.IsDefault = false; - mediaStream.Title = null; - - var fileNameWithoutExtension = NormalizeFilenameForAudioComparison(fullName); - // The audio filename must either be equal to the video filename or start with the video filename followed by a dot - if (videoFileNameWithoutExtension.Equals(fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) - { - mediaStream.Path = fullName; - } - else if (fileNameWithoutExtension.Length > videoFileNameWithoutExtension.Length + if (videoFileNameWithoutExtension.Equals(fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase) || + (fileNameWithoutExtension.Length > videoFileNameWithoutExtension.Length && fileNameWithoutExtension[videoFileNameWithoutExtension.Length] == '.' - && fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) + && fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))) { - - // Support xbmc naming conventions - 300.spanish.m4a - var languageSpan = fileNameWithoutExtension; - while (languageSpan.Length > 0) - { - var lastDot = languageSpan.LastIndexOf('.'); - var currentSlice = languageSpan[lastDot..]; - languageSpan = languageSpan[(lastDot + 1)..]; - break; - } - - // Try to translate to three character code - // Be flexible and check against both the full and three character versions - var language = languageSpan.ToString(); - var culture = _localization.FindLanguageInfo(language); - - language = culture == null ? language : culture.ThreeLetterISOLanguageName; - mediaStream.Language = language; - } - else - { - continue; + paths.Add(files[i]); } - - mediaStream.Codec = extension.TrimStart('.').ToString().ToLowerInvariant(); - - streams.Add(mediaStream); } + + return paths; } - private static bool IsAudioExtension(ReadOnlySpan extension) + public async Task AddExternalAudioStreams( + List streams, + List paths, + int startIndex, + ILocalizationManager localizationManager, + IMediaEncoder mediaEncoder, + CancellationToken cancellationToken) { - String[] audioExtensions = new[] + foreach (string path in paths) { - ".nsv", - ".m4a", - ".flac", - ".aac", - ".strm", - ".pls", - ".rm", - ".mpa", - ".wav", - ".wma", - ".ogg", - ".opus", - ".mp3", - ".mp2", - ".mod", - ".amf", - ".669", - ".dmf", - ".dsm", - ".far", - ".gdm", - ".imf", - ".it", - ".m15", - ".med", - ".okt", - ".s3m", - ".stm", - ".sfx", - ".ult", - ".uni", - ".xm", - ".sid", - ".ac3", - ".dts", - ".cue", - ".aif", - ".aiff", - ".ape", - ".mac", - ".mpc", - ".mp+", - ".mpp", - ".shn", - ".wv", - ".nsf", - ".spc", - ".gym", - ".adplug", - ".adx", - ".dsp", - ".adp", - ".ymf", - ".ast", - ".afc", - ".hps", - ".xsp", - ".acc", - ".m4b", - ".oga", - ".dsf", - ".mka" - }; + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); + Model.MediaInfo.MediaInfo mediaInfo = await GetMediaInfo(path, mediaEncoder, cancellationToken); - foreach (String audioExtension in audioExtensions) - { - if (extension.Equals(audioExtension, StringComparison.OrdinalIgnoreCase)) + foreach (MediaStream mediaStream in mediaInfo.MediaStreams) { - return true; + mediaStream.Index = startIndex++; + mediaStream.Type = MediaStreamType.Audio; + mediaStream.IsExternal = true; + mediaStream.Path = path; + mediaStream.IsDefault = false; + mediaStream.Title = null; + + if (mediaStream.Language == null) + { + // Try to translate to three character code + // Be flexible and check against both the full and three character versions + var language = StringExtensions.RightPart(fileNameWithoutExtension, '.').ToString(); + + if (language != fileNameWithoutExtension) + { + var culture = localizationManager.FindLanguageInfo(language); + + language = culture == null ? language : culture.ThreeLetterISOLanguageName; + mediaStream.Language = language; + } + } + + streams.Add(mediaStream); } } - - return false; } - private Task GetMediaInfo(string path) + private Task GetMediaInfo(string path, IMediaEncoder mediaEncoder, CancellationToken cancellationToken) { - _cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); - return _mediaEncoder.GetMediaInfo( + return mediaEncoder.GetMediaInfo( new MediaInfoRequest { MediaType = DlnaProfileType.Audio, @@ -248,28 +158,7 @@ namespace MediaBrowser.Providers.MediaInfo Protocol = MediaProtocol.File } }, - _cancellationToken); - } - - private static ReadOnlySpan NormalizeFilenameForAudioComparison(string filename) - { - // Try to account for sloppy file naming - filename = filename.Replace("_", string.Empty, StringComparison.Ordinal); - filename = filename.Replace(" ", string.Empty, StringComparison.Ordinal); - return Path.GetFileNameWithoutExtension(filename.AsSpan()); - } - - private void AddExternalAudioStreams( - List streams, - string folder, - string videoPath, - int startIndex, - IDirectoryService directoryService, - bool clearCache) - { - var files = directoryService.GetFilePaths(folder, clearCache, true); - - AddExternalAudioStreams(streams, videoPath, startIndex, files); + cancellationToken); } } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 1e7fcf2d2..98909c94e 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Emby.Naming.Common; using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -50,10 +51,10 @@ namespace MediaBrowser.Providers.MediaInfo private readonly IMediaSourceManager _mediaSourceManager; private readonly SubtitleResolver _subtitleResolver; - private readonly AudioResolver _audioResolver; - private readonly Task _cachedTask = Task.FromResult(ItemUpdateType.None); + private readonly NamingOptions _namingOptions; + public FFProbeProvider( ILogger logger, IMediaSourceManager mediaSourceManager, @@ -65,7 +66,8 @@ namespace MediaBrowser.Providers.MediaInfo IServerConfigurationManager config, ISubtitleManager subtitleManager, IChapterManager chapterManager, - ILibraryManager libraryManager) + ILibraryManager libraryManager, + NamingOptions namingOptions) { _logger = logger; _mediaEncoder = mediaEncoder; @@ -78,9 +80,9 @@ namespace MediaBrowser.Providers.MediaInfo _chapterManager = chapterManager; _libraryManager = libraryManager; _mediaSourceManager = mediaSourceManager; + _namingOptions = namingOptions; _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager); - _audioResolver = new AudioResolver(BaseItem.LocalizationManager, mediaEncoder); } public string Name => "ffprobe"; @@ -114,9 +116,10 @@ namespace MediaBrowser.Providers.MediaInfo return true; } + AudioResolver audioResolver = new AudioResolver(); if (item.SupportsLocalMetadata && video != null && !video.IsPlaceHolder && !video.AudioFiles.SequenceEqual( - _audioResolver.GetExternalAudioFiles(video, directoryService, false), StringComparer.Ordinal)) + audioResolver.GetExternalAudioFiles(video, directoryService, _namingOptions, false), StringComparer.Ordinal)) { _logger.LogDebug("Refreshing {0} due to external audio change.", item.Path); return true; @@ -199,7 +202,8 @@ namespace MediaBrowser.Providers.MediaInfo _config, _subtitleManager, _chapterManager, - _libraryManager); + _libraryManager, + _namingOptions); return prober.ProbeVideo(item, options, cancellationToken); } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 2d49e43ca..39950db70 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using DvdLib.Ifo; +using Emby.Naming.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Configuration; @@ -44,6 +45,7 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ISubtitleManager _subtitleManager; private readonly IChapterManager _chapterManager; private readonly ILibraryManager _libraryManager; + private readonly NamingOptions _namingOptions; private readonly IMediaSourceManager _mediaSourceManager; private readonly long _dummyChapterDuration = TimeSpan.FromMinutes(5).Ticks; @@ -59,7 +61,8 @@ namespace MediaBrowser.Providers.MediaInfo IServerConfigurationManager config, ISubtitleManager subtitleManager, IChapterManager chapterManager, - ILibraryManager libraryManager) + ILibraryManager libraryManager, + NamingOptions namingOptions) { _logger = logger; _mediaEncoder = mediaEncoder; @@ -71,6 +74,7 @@ namespace MediaBrowser.Providers.MediaInfo _subtitleManager = subtitleManager; _chapterManager = chapterManager; _libraryManager = libraryManager; + _namingOptions = namingOptions; _mediaSourceManager = mediaSourceManager; } @@ -214,7 +218,7 @@ namespace MediaBrowser.Providers.MediaInfo await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false); - AddExternalAudio(video, mediaStreams, options, cancellationToken); + await AddExternalAudio(video, mediaStreams, options, cancellationToken); var libraryOptions = _libraryManager.GetLibraryOptions(video); @@ -583,18 +587,18 @@ namespace MediaBrowser.Providers.MediaInfo /// The current streams. /// The refreshOptions. /// The cancellation token. - private void AddExternalAudio( + private async Task AddExternalAudio( Video video, List currentStreams, MetadataRefreshOptions options, CancellationToken cancellationToken) { - var audioResolver = new AudioResolver(_localization, _mediaEncoder, cancellationToken); + var audioResolver = new AudioResolver(); var startIndex = currentStreams.Count == 0 ? 0 : currentStreams.Max(i => i.Index) + 1; - var externalAudioStreams = audioResolver.GetExternalAudioStreams(video, startIndex, options.DirectoryService, false); + var externalAudioStreams = await audioResolver.GetExternalAudioStreams(video, startIndex, options.DirectoryService, _namingOptions, false, _localization, _mediaEncoder, cancellationToken); - video.AudioFiles = externalAudioStreams.Select(i => i.Path).ToArray(); + video.AudioFiles = externalAudioStreams.Select(i => i.Path).Distinct().ToArray(); currentStreams.AddRange(externalAudioStreams); } -- cgit v1.2.3 From 0894a6193f025a9cec5c735226a8487caa2bc66b Mon Sep 17 00:00:00 2001 From: Jonas Resch Date: Sun, 28 Nov 2021 14:03:52 +0100 Subject: Implement coding standards from 2nd code feedback --- .../MediaEncoding/EncodingHelper.cs | 3 +- MediaBrowser.Providers/MediaInfo/AudioResolver.cs | 138 +++++++++------------ .../MediaInfo/FFProbeProvider.cs | 15 ++- .../MediaInfo/FFProbeVideoInfo.cs | 21 ++-- 4 files changed, 78 insertions(+), 99 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 5695ee2db..571230312 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -698,8 +698,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.AudioStream != null && state.AudioStream.IsExternal) { - arg.Append(" -i ") - .Append(string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", state.AudioStream.Path)); + arg.Append(" -i \"").Append(state.AudioStream.Path).Append("\""); } return arg.ToString(); diff --git a/MediaBrowser.Providers/MediaInfo/AudioResolver.cs b/MediaBrowser.Providers/MediaInfo/AudioResolver.cs index ccac450f6..d23afdc3b 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioResolver.cs @@ -21,69 +21,93 @@ namespace MediaBrowser.Providers.MediaInfo { public class AudioResolver { - public async Task> GetExternalAudioStreams( + private readonly ILocalizationManager _localizationManager; + private readonly IMediaEncoder _mediaEncoder; + private readonly NamingOptions _namingOptions; + + public AudioResolver( + ILocalizationManager localizationManager, + IMediaEncoder mediaEncoder, + NamingOptions namingOptions) + { + _localizationManager = localizationManager; + _mediaEncoder = mediaEncoder; + _namingOptions = namingOptions; + } + + public async IAsyncEnumerable GetExternalAudioStreams( Video video, int startIndex, IDirectoryService directoryService, - NamingOptions namingOptions, bool clearCache, - ILocalizationManager localizationManager, - IMediaEncoder mediaEncoder, CancellationToken cancellationToken) { - var streams = new List(); - if (!video.IsFileProtocol) { - return streams; + yield break; } - List paths = GetExternalAudioFiles(video, directoryService, namingOptions, clearCache); + IEnumerable paths = GetExternalAudioFiles(video, directoryService, clearCache); + foreach (string path in paths) + { + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); + Model.MediaInfo.MediaInfo mediaInfo = await GetMediaInfo(path, cancellationToken); - await AddExternalAudioStreams(streams, paths, startIndex, localizationManager, mediaEncoder, cancellationToken).ConfigureAwait(false); + foreach (MediaStream mediaStream in mediaInfo.MediaStreams) + { + mediaStream.Index = startIndex++; + mediaStream.Type = MediaStreamType.Audio; + mediaStream.IsExternal = true; + mediaStream.Path = path; + mediaStream.IsDefault = false; + mediaStream.Title = null; - return streams; + if (string.IsNullOrEmpty(mediaStream.Language)) + { + // Try to translate to three character code + // Be flexible and check against both the full and three character versions + var language = StringExtensions.RightPart(fileNameWithoutExtension, '.').ToString(); + + if (language != fileNameWithoutExtension) + { + var culture = _localizationManager.FindLanguageInfo(language); + + language = culture == null ? language : culture.ThreeLetterISOLanguageName; + mediaStream.Language = language; + } + } + + yield return mediaStream; + } + } } public IEnumerable GetExternalAudioFiles( Video video, IDirectoryService directoryService, - NamingOptions namingOptions, bool clearCache) { - List paths = new List(); - if (!video.IsFileProtocol) { - return paths; + yield break; } - paths.AddRange(GetAudioFilesFromFolder(video.ContainingFolderPath, video.Path, directoryService, namingOptions, clearCache)); - - return paths; - } - - private List GetAudioFilesFromFolder( - string folder, - string videoFileName, - IDirectoryService directoryService, - NamingOptions namingOptions, - bool clearCache) - { - List paths = new List(); - string videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(videoFileName); - + // Check if video folder exists + string folder = video.ContainingFolderPath; if (!Directory.Exists(folder)) { - return paths; + yield break; } + string videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path); + var files = directoryService.GetFilePaths(folder, clearCache, true); for (int i = 0; i < files.Count; i++) { - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(files[i]); + string file = files[i]; + string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); - if (!AudioFileParser.IsAudioFile(files[i], namingOptions)) + if (!AudioFileParser.IsAudioFile(file, _namingOptions)) { continue; } @@ -94,60 +118,16 @@ namespace MediaBrowser.Providers.MediaInfo && fileNameWithoutExtension[videoFileNameWithoutExtension.Length] == '.' && fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))) { - paths.Add(files[i]); - } - } - - return paths; - } - - public async Task AddExternalAudioStreams( - List streams, - List paths, - int startIndex, - ILocalizationManager localizationManager, - IMediaEncoder mediaEncoder, - CancellationToken cancellationToken) - { - foreach (string path in paths) - { - string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); - Model.MediaInfo.MediaInfo mediaInfo = await GetMediaInfo(path, mediaEncoder, cancellationToken); - - foreach (MediaStream mediaStream in mediaInfo.MediaStreams) - { - mediaStream.Index = startIndex++; - mediaStream.Type = MediaStreamType.Audio; - mediaStream.IsExternal = true; - mediaStream.Path = path; - mediaStream.IsDefault = false; - mediaStream.Title = null; - - if (string.IsNullOrEmpty(mediaStream.Language)) - { - // Try to translate to three character code - // Be flexible and check against both the full and three character versions - var language = StringExtensions.RightPart(fileNameWithoutExtension, '.').ToString(); - - if (language != fileNameWithoutExtension) - { - var culture = localizationManager.FindLanguageInfo(language); - - language = culture == null ? language : culture.ThreeLetterISOLanguageName; - mediaStream.Language = language; - } - } - - streams.Add(mediaStream); + yield return file; } } } - private Task GetMediaInfo(string path, IMediaEncoder mediaEncoder, CancellationToken cancellationToken) + private Task GetMediaInfo(string path, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - return mediaEncoder.GetMediaInfo( + return _mediaEncoder.GetMediaInfo( new MediaInfoRequest { MediaType = DlnaProfileType.Audio, diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 98909c94e..392641468 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -50,10 +50,9 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly SubtitleResolver _subtitleResolver; - private readonly Task _cachedTask = Task.FromResult(ItemUpdateType.None); - private readonly NamingOptions _namingOptions; + private readonly AudioResolver _audioResolver; public FFProbeProvider( ILogger logger, @@ -83,6 +82,7 @@ namespace MediaBrowser.Providers.MediaInfo _namingOptions = namingOptions; _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager); + _audioResolver = new AudioResolver(_localization, _mediaEncoder, namingOptions); } public string Name => "ffprobe"; @@ -102,7 +102,7 @@ namespace MediaBrowser.Providers.MediaInfo var file = directoryService.GetFile(path); if (file != null && file.LastWriteTimeUtc != item.DateModified) { - _logger.LogDebug("Refreshing {0} due to date modified timestamp change.", path); + _logger.LogDebug("Refreshing {ItemPath} due to date modified timestamp change.", path); return true; } } @@ -112,16 +112,15 @@ namespace MediaBrowser.Providers.MediaInfo && !video.SubtitleFiles.SequenceEqual( _subtitleResolver.GetExternalSubtitleFiles(video, directoryService, false), StringComparer.Ordinal)) { - _logger.LogDebug("Refreshing {0} due to external subtitles change.", item.Path); + _logger.LogDebug("Refreshing {ItemPath} due to external subtitles change.", item.Path); return true; } - AudioResolver audioResolver = new AudioResolver(); if (item.SupportsLocalMetadata && video != null && !video.IsPlaceHolder && !video.AudioFiles.SequenceEqual( - audioResolver.GetExternalAudioFiles(video, directoryService, _namingOptions, false), StringComparer.Ordinal)) + _audioResolver.GetExternalAudioFiles(video, directoryService, false), StringComparer.Ordinal)) { - _logger.LogDebug("Refreshing {0} due to external audio change.", item.Path); + _logger.LogDebug("Refreshing {ItemPath} due to external audio change.", item.Path); return true; } @@ -203,7 +202,7 @@ namespace MediaBrowser.Providers.MediaInfo _subtitleManager, _chapterManager, _libraryManager, - _namingOptions); + _audioResolver); return prober.ProbeVideo(item, options, cancellationToken); } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 745020599..b31f0ed23 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -10,7 +10,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using DvdLib.Ifo; -using Emby.Naming.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Configuration; @@ -45,7 +44,7 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ISubtitleManager _subtitleManager; private readonly IChapterManager _chapterManager; private readonly ILibraryManager _libraryManager; - private readonly NamingOptions _namingOptions; + private readonly AudioResolver _audioResolver; private readonly IMediaSourceManager _mediaSourceManager; private readonly long _dummyChapterDuration = TimeSpan.FromMinutes(5).Ticks; @@ -62,7 +61,7 @@ namespace MediaBrowser.Providers.MediaInfo ISubtitleManager subtitleManager, IChapterManager chapterManager, ILibraryManager libraryManager, - NamingOptions namingOptions) + AudioResolver audioResolver) { _logger = logger; _mediaEncoder = mediaEncoder; @@ -74,7 +73,7 @@ namespace MediaBrowser.Providers.MediaInfo _subtitleManager = subtitleManager; _chapterManager = chapterManager; _libraryManager = libraryManager; - _namingOptions = namingOptions; + _audioResolver = audioResolver; _mediaSourceManager = mediaSourceManager; } @@ -218,7 +217,7 @@ namespace MediaBrowser.Providers.MediaInfo await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false); - await AddExternalAudio(video, mediaStreams, options, cancellationToken).ConfigureAwait(false); + await AddExternalAudio(video, mediaStreams, options, cancellationToken); var libraryOptions = _libraryManager.GetLibraryOptions(video); @@ -593,14 +592,16 @@ namespace MediaBrowser.Providers.MediaInfo MetadataRefreshOptions options, CancellationToken cancellationToken) { - var audioResolver = new AudioResolver(); - var startIndex = currentStreams.Count == 0 ? 0 : currentStreams.Max(i => i.Index) + 1; - var externalAudioStreams = await audioResolver.GetExternalAudioStreams(video, startIndex, options.DirectoryService, _namingOptions, false, _localization, _mediaEncoder, cancellationToken); + var externalAudioStreams = _audioResolver.GetExternalAudioStreams(video, startIndex, options.DirectoryService, false, cancellationToken); - video.AudioFiles = externalAudioStreams.Select(i => i.Path).Distinct().ToArray(); + await foreach (MediaStream externalAudioStream in externalAudioStreams) + { + currentStreams.Add(externalAudioStream); + } - currentStreams.AddRange(externalAudioStreams); + // Select all external audio file paths + video.AudioFiles = currentStreams.Where(i => i.Type == MediaStreamType.Audio && i.IsExternal).Select(i => i.Path).Distinct().ToArray(); } /// -- cgit v1.2.3 From 120828d8d03da08a55edfbce5bfe1463bf06eae3 Mon Sep 17 00:00:00 2001 From: Jonas Resch <32968142+jonas-resch@users.noreply.github.com> Date: Fri, 3 Dec 2021 19:18:43 +0100 Subject: Replace escaped quote string with quote character in MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs Co-authored-by: Cody Robibero --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 571230312..92b345f12 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -698,7 +698,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.AudioStream != null && state.AudioStream.IsExternal) { - arg.Append(" -i \"").Append(state.AudioStream.Path).Append("\""); + arg.Append(" -i \"").Append(state.AudioStream.Path).Append('"'); } return arg.ToString(); -- cgit v1.2.3 From 99a48554a618302b4fe70ef1fd3d7fd06096c70e Mon Sep 17 00:00:00 2001 From: Jonas Resch <32968142+jonas-resch@users.noreply.github.com> Date: Fri, 3 Dec 2021 19:19:22 +0100 Subject: Optimize calculation of external audio stream index in MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs Co-authored-by: Cody Robibero --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 92b345f12..91f6654bb 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -2007,7 +2007,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.AudioStream.IsExternal) { int externalAudioMapIndex = state.SubtitleStream != null && state.SubtitleStream.IsExternal ? 2 : 1; - int externalAudioStream = state.MediaSource.MediaStreams.Where(i => i.Path == state.AudioStream.Path).ToList().IndexOf(state.AudioStream); + int externalAudioStream = state.MediaSource.MediaStreams.FindIndex(i => i.Path == state.AudioStream.Path); args += string.Format( CultureInfo.InvariantCulture, -- cgit v1.2.3 From d47811bdaf8bbfc74c8185ef0bff7490726828d9 Mon Sep 17 00:00:00 2001 From: Jonas Resch Date: Wed, 8 Dec 2021 10:17:25 +0100 Subject: Fix wrong ffmpeg map argument due to wrong calculation --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 91f6654bb..92b345f12 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -2007,7 +2007,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.AudioStream.IsExternal) { int externalAudioMapIndex = state.SubtitleStream != null && state.SubtitleStream.IsExternal ? 2 : 1; - int externalAudioStream = state.MediaSource.MediaStreams.FindIndex(i => i.Path == state.AudioStream.Path); + int externalAudioStream = state.MediaSource.MediaStreams.Where(i => i.Path == state.AudioStream.Path).ToList().IndexOf(state.AudioStream); args += string.Format( CultureInfo.InvariantCulture, -- cgit v1.2.3