Skip to content

Commit

Permalink
Audio normalization: parse ffmpeg output line by line
Browse files Browse the repository at this point in the history
Should prevent OOM error
Also optimized the regex so it can bail out earlier
  • Loading branch information
Bond-009 committed Jun 1, 2024
1 parent 0392daa commit bc8ef94
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
Expand Down Expand Up @@ -69,7 +70,7 @@ public AudioNormalizationTask(
/// <inheritdoc />
public string Key => "AudioNormalization";

[GeneratedRegex(@"I:\s+(.*?)\s+LUFS")]
[GeneratedRegex(@"^\s+I:\s+(.*?)\s+LUFS")]
private static partial Regex LUFSRegex();

/// <inheritdoc />
Expand Down Expand Up @@ -179,16 +180,17 @@ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
}

using var reader = process.StandardError;
var output = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
MatchCollection split = LUFSRegex().Matches(output);

if (split.Count != 0)
await foreach (var line in reader.ReadAllLinesAsync(cancellationToken))
{
return float.Parse(split[0].Groups[1].ValueSpan, CultureInfo.InvariantCulture.NumberFormat);
Match match = LUFSRegex().Match(line);

if (match.Success)
{
return float.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture.NumberFormat);
}
}

_logger.LogError("Failed to find LUFS value in output:\n{Output}", output);
_logger.LogError("Failed to find LUFS value in output");
return null;
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/Jellyfin.Extensions/StreamExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;

namespace Jellyfin.Extensions
{
Expand Down Expand Up @@ -48,11 +50,12 @@ public static IEnumerable<string> ReadAllLines(this TextReader reader)
/// Reads all lines in the <see cref="TextReader" />.
/// </summary>
/// <param name="reader">The <see cref="TextReader" /> to read from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>All lines in the stream.</returns>
public static async IAsyncEnumerable<string> ReadAllLinesAsync(this TextReader reader)
public static async IAsyncEnumerable<string> ReadAllLinesAsync(this TextReader reader, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
string? line;
while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) is not null)
while ((line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false)) is not null)
{
yield return line;
}
Expand Down

0 comments on commit bc8ef94

Please sign in to comment.