From 9ffb07d67fd7d2c08cafff9081f38faac51b7e43 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 30 Apr 2024 16:16:42 +0200 Subject: Fix filename --- .../Tasks/AudioNormalizationPostScanTask.cs | 195 --------------------- .../ScheduledTasks/Tasks/AudioNormalizationTask.cs | 195 +++++++++++++++++++++ 2 files changed, 195 insertions(+), 195 deletions(-) delete mode 100644 Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationPostScanTask.cs create mode 100644 Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationPostScanTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationPostScanTask.cs deleted file mode 100644 index 04d6ed0f2..000000000 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationPostScanTask.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Jellyfin.Data.Enums; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Tasks; -using Microsoft.Extensions.Logging; - -namespace Emby.Server.Implementations.ScheduledTasks.Tasks; - -/// -/// The audio normalization task. -/// -public partial class AudioNormalizationTask : IScheduledTask -{ - private readonly IItemRepository _itemRepository; - private readonly ILibraryManager _libraryManager; - private readonly IMediaEncoder _mediaEncoder; - private readonly IConfigurationManager _configurationManager; - private readonly ILocalizationManager _localization; - private readonly ILogger _logger; - - /// - /// Initializes a new instance of the class. - /// - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - public AudioNormalizationTask( - IItemRepository itemRepository, - ILibraryManager libraryManager, - IMediaEncoder mediaEncoder, - IConfigurationManager configurationManager, - ILocalizationManager localizationManager, - ILogger logger) - { - _itemRepository = itemRepository; - _libraryManager = libraryManager; - _mediaEncoder = mediaEncoder; - _configurationManager = configurationManager; - _localization = localizationManager; - _logger = logger; - } - - /// - public string Name => _localization.GetLocalizedString("TaskAudioNormalization"); - - /// - public string Description => _localization.GetLocalizedString("TaskAudioNormalizationDescription"); - - /// - public string Category => _localization.GetLocalizedString("TasksLibraryCategory"); - - /// - public string Key => "AudioNormalization"; - - [GeneratedRegex(@"I:\s+(.*?)\s+LUFS")] - private static partial Regex LUFSRegex(); - - /// - public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) - { - foreach (var library in _libraryManager.RootFolder.Children) - { - var libraryOptions = _libraryManager.GetLibraryOptions(library); - if (!libraryOptions.EnableLUFSScan) - { - continue; - } - - // Album gain - var albums = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = [BaseItemKind.MusicAlbum], - Parent = library, - Recursive = true - }); - - foreach (var a in albums) - { - if (a.NormalizationGain.HasValue || a.LUFS.HasValue) - { - continue; - } - - // Skip albums that don't have multiple tracks, album gain is useless here - var albumTracks = ((MusicAlbum)a).Tracks.Where(x => x.IsFileProtocol).ToList(); - if (albumTracks.Count <= 1) - { - continue; - } - - var tempFile = Path.Join(_configurationManager.GetTranscodePath(), Guid.NewGuid() + ".concat"); - var inputLines = albumTracks.Select(x => string.Format(CultureInfo.InvariantCulture, "file '{0}'", x.Path.Replace("'", @"'\''", StringComparison.Ordinal))); - await File.WriteAllLinesAsync(tempFile, inputLines, cancellationToken).ConfigureAwait(false); - a.LUFS = await CalculateLUFSAsync( - string.Format(CultureInfo.InvariantCulture, "-f concat -safe 0 -i \"{0}\"", tempFile), - cancellationToken).ConfigureAwait(false); - File.Delete(tempFile); - } - - _itemRepository.SaveItems(albums, cancellationToken); - - // Track gain - var tracks = _libraryManager.GetItemList(new InternalItemsQuery - { - MediaTypes = [MediaType.Audio], - IncludeItemTypes = [BaseItemKind.Audio], - Parent = library, - Recursive = true - }); - - foreach (var t in tracks) - { - if (t.NormalizationGain.HasValue || t.LUFS.HasValue || !t.IsFileProtocol) - { - continue; - } - - t.LUFS = await CalculateLUFSAsync(string.Format(CultureInfo.InvariantCulture, "-i \"{0}\"", t.Path.Replace("\"", "\\\"", StringComparison.Ordinal)), cancellationToken); - } - - _itemRepository.SaveItems(tracks, cancellationToken); - } - } - - /// - public IEnumerable GetDefaultTriggers() - { - return - [ - new TaskTriggerInfo - { - Type = TaskTriggerInfo.TriggerInterval, - IntervalTicks = TimeSpan.FromHours(24).Ticks - } - ]; - } - - private async Task CalculateLUFSAsync(string inputArgs, CancellationToken cancellationToken) - { - var args = $"-hide_banner {inputArgs} -af ebur128=framelog=verbose -f null -"; - - using (var process = new Process() - { - StartInfo = new ProcessStartInfo - { - FileName = _mediaEncoder.EncoderPath, - Arguments = args, - RedirectStandardOutput = false, - RedirectStandardError = true - }, - }) - { - try - { - _logger.LogDebug("Starting ffmpeg with arguments: {Arguments}", args); - process.Start(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error starting ffmpeg with arguments: {Arguments}", args); - return null; - } - - using var reader = process.StandardError; - var output = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false); - cancellationToken.ThrowIfCancellationRequested(); - MatchCollection split = LUFSRegex().Matches(output); - - if (split.Count != 0) - { - return float.Parse(split[0].Groups[1].ValueSpan, CultureInfo.InvariantCulture.NumberFormat); - } - - _logger.LogError("Failed to find LUFS value in output:\n{Output}", output); - return null; - } - } -} diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs new file mode 100644 index 000000000..04d6ed0f2 --- /dev/null +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/AudioNormalizationTask.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace Emby.Server.Implementations.ScheduledTasks.Tasks; + +/// +/// The audio normalization task. +/// +public partial class AudioNormalizationTask : IScheduledTask +{ + private readonly IItemRepository _itemRepository; + private readonly ILibraryManager _libraryManager; + private readonly IMediaEncoder _mediaEncoder; + private readonly IConfigurationManager _configurationManager; + private readonly ILocalizationManager _localization; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + public AudioNormalizationTask( + IItemRepository itemRepository, + ILibraryManager libraryManager, + IMediaEncoder mediaEncoder, + IConfigurationManager configurationManager, + ILocalizationManager localizationManager, + ILogger logger) + { + _itemRepository = itemRepository; + _libraryManager = libraryManager; + _mediaEncoder = mediaEncoder; + _configurationManager = configurationManager; + _localization = localizationManager; + _logger = logger; + } + + /// + public string Name => _localization.GetLocalizedString("TaskAudioNormalization"); + + /// + public string Description => _localization.GetLocalizedString("TaskAudioNormalizationDescription"); + + /// + public string Category => _localization.GetLocalizedString("TasksLibraryCategory"); + + /// + public string Key => "AudioNormalization"; + + [GeneratedRegex(@"I:\s+(.*?)\s+LUFS")] + private static partial Regex LUFSRegex(); + + /// + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) + { + foreach (var library in _libraryManager.RootFolder.Children) + { + var libraryOptions = _libraryManager.GetLibraryOptions(library); + if (!libraryOptions.EnableLUFSScan) + { + continue; + } + + // Album gain + var albums = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = [BaseItemKind.MusicAlbum], + Parent = library, + Recursive = true + }); + + foreach (var a in albums) + { + if (a.NormalizationGain.HasValue || a.LUFS.HasValue) + { + continue; + } + + // Skip albums that don't have multiple tracks, album gain is useless here + var albumTracks = ((MusicAlbum)a).Tracks.Where(x => x.IsFileProtocol).ToList(); + if (albumTracks.Count <= 1) + { + continue; + } + + var tempFile = Path.Join(_configurationManager.GetTranscodePath(), Guid.NewGuid() + ".concat"); + var inputLines = albumTracks.Select(x => string.Format(CultureInfo.InvariantCulture, "file '{0}'", x.Path.Replace("'", @"'\''", StringComparison.Ordinal))); + await File.WriteAllLinesAsync(tempFile, inputLines, cancellationToken).ConfigureAwait(false); + a.LUFS = await CalculateLUFSAsync( + string.Format(CultureInfo.InvariantCulture, "-f concat -safe 0 -i \"{0}\"", tempFile), + cancellationToken).ConfigureAwait(false); + File.Delete(tempFile); + } + + _itemRepository.SaveItems(albums, cancellationToken); + + // Track gain + var tracks = _libraryManager.GetItemList(new InternalItemsQuery + { + MediaTypes = [MediaType.Audio], + IncludeItemTypes = [BaseItemKind.Audio], + Parent = library, + Recursive = true + }); + + foreach (var t in tracks) + { + if (t.NormalizationGain.HasValue || t.LUFS.HasValue || !t.IsFileProtocol) + { + continue; + } + + t.LUFS = await CalculateLUFSAsync(string.Format(CultureInfo.InvariantCulture, "-i \"{0}\"", t.Path.Replace("\"", "\\\"", StringComparison.Ordinal)), cancellationToken); + } + + _itemRepository.SaveItems(tracks, cancellationToken); + } + } + + /// + public IEnumerable GetDefaultTriggers() + { + return + [ + new TaskTriggerInfo + { + Type = TaskTriggerInfo.TriggerInterval, + IntervalTicks = TimeSpan.FromHours(24).Ticks + } + ]; + } + + private async Task CalculateLUFSAsync(string inputArgs, CancellationToken cancellationToken) + { + var args = $"-hide_banner {inputArgs} -af ebur128=framelog=verbose -f null -"; + + using (var process = new Process() + { + StartInfo = new ProcessStartInfo + { + FileName = _mediaEncoder.EncoderPath, + Arguments = args, + RedirectStandardOutput = false, + RedirectStandardError = true + }, + }) + { + try + { + _logger.LogDebug("Starting ffmpeg with arguments: {Arguments}", args); + process.Start(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error starting ffmpeg with arguments: {Arguments}", args); + return null; + } + + using var reader = process.StandardError; + var output = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + MatchCollection split = LUFSRegex().Matches(output); + + if (split.Count != 0) + { + return float.Parse(split[0].Groups[1].ValueSpan, CultureInfo.InvariantCulture.NumberFormat); + } + + _logger.LogError("Failed to find LUFS value in output:\n{Output}", output); + return null; + } + } +} -- cgit v1.2.3