mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2026-05-02 09:09:08 -05:00
Fixing issue with audio normalization and -inif
This commit is contained in:
@@ -133,6 +133,12 @@ public class FfmpegBuilderAudioAddTrack : FfmpegBuilderNode
|
||||
|
||||
internal AudioStream GetBestAudioTrack(NodeParameters args, IEnumerable<AudioStream> streams)
|
||||
{
|
||||
Regex? rgxLanguage = null;
|
||||
try
|
||||
{
|
||||
rgxLanguage = new Regex(this.Language, RegexOptions.IgnoreCase);
|
||||
}
|
||||
catch (Exception) { }
|
||||
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
|
||||
var bestAudio = streams.Where(x => System.Text.Json.JsonSerializer.Serialize(x).ToLower().Contains("commentary") == false)
|
||||
#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
|
||||
@@ -143,6 +149,8 @@ public class FfmpegBuilderAudioAddTrack : FfmpegBuilderNode
|
||||
args.Logger?.ILog("Language: " + x.Language, x);
|
||||
if (string.IsNullOrEmpty(x.Language))
|
||||
return 50; // no language specified
|
||||
if (rgxLanguage != null && rgxLanguage.IsMatch(x.Language))
|
||||
return 0;
|
||||
if (x.Language.ToLower() != Language)
|
||||
return 100; // low priority not the desired language
|
||||
}
|
||||
|
||||
@@ -1,138 +1,146 @@
|
||||
#if(DEBUG)
|
||||
|
||||
namespace VideoNodes.Tests
|
||||
namespace VideoNodes.Tests;
|
||||
|
||||
using FileFlows.VideoNodes;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
[TestClass]
|
||||
public class AudioNormalizationTests:TestBase
|
||||
{
|
||||
using FileFlows.VideoNodes;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
[TestClass]
|
||||
public class AudioNormalizationTests
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Test_DoTwoPassMethod()
|
||||
{
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Test_DoTwoPassMethod()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\The IT Crowd - 2x04 - The Dinner Party.avi";
|
||||
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", new TestLogger());
|
||||
var vii = vi.Read(file);
|
||||
string file = TestFile_BasicMkv;
|
||||
var vi = new VideoInfoHelper(FfmpegPath, new TestLogger());
|
||||
var vii = vi.Read(file);
|
||||
|
||||
const string ffmpeg = @"C:\utils\ffmpeg\ffmpeg.exe";
|
||||
|
||||
AudioNormalization node = new();
|
||||
//node.OutputFile = file + ".sup";
|
||||
var args = new FileFlows.Plugin.NodeParameters(file, new TestLogger(), false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => ffmpeg;
|
||||
args.TempPath = @"D:\videos\temp";
|
||||
AudioNormalization node = new();
|
||||
//node.OutputFile = file + ".sup";
|
||||
var args = new FileFlows.Plugin.NodeParameters(file, new TestLogger(), false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => FfmpegPath;
|
||||
args.TempPath = TempPath;
|
||||
|
||||
new VideoFile().Execute(args);
|
||||
new VideoFile().Execute(args);
|
||||
|
||||
string output = AudioNormalization.DoTwoPass(node, args, ffmpeg, 0);
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(output));
|
||||
}
|
||||
string output = AudioNormalization.DoTwoPass(node, args, FfmpegPath, 0);
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(output));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Test_TwoPass()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\The IT Crowd - 2x04 - The Dinner Party.avi";
|
||||
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", new TestLogger());
|
||||
var vii = vi.Read(file);
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Test_TwoPass()
|
||||
{
|
||||
string file = TestFile_BasicMkv;
|
||||
var vi = new VideoInfoHelper(FfmpegPath, new TestLogger());
|
||||
var vii = vi.Read(file);
|
||||
|
||||
const string ffmpeg = @"C:\utils\ffmpeg\ffmpeg.exe";
|
||||
AudioNormalization node = new();
|
||||
node.TwoPass = true;
|
||||
//node.OutputFile = file + ".sup";
|
||||
var args = new NodeParameters(file, new TestLogger(), false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => FfmpegPath;
|
||||
args.TempPath = TempPath;
|
||||
|
||||
AudioNormalization node = new();
|
||||
node.TwoPass = true;
|
||||
//node.OutputFile = file + ".sup";
|
||||
var args = new FileFlows.Plugin.NodeParameters(file, new TestLogger(), false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => ffmpeg;
|
||||
args.TempPath = @"D:\videos\temp";
|
||||
new VideoFile().Execute(args);
|
||||
|
||||
new VideoFile().Execute(args);
|
||||
int output = node.Execute(args);
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
|
||||
int output = node.Execute(args);
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Pattern_Test()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\Masters of the Universe (1987) Bluray-1080p.mkv";
|
||||
var logger = new TestLogger();
|
||||
var vi = new VideoInfoHelper(FfmpegPath, logger);
|
||||
var vii = vi.Read(file);
|
||||
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Pattern_Test()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\Masters of the Universe (1987) Bluray-1080p.mkv";
|
||||
var logger = new TestLogger();
|
||||
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", logger);
|
||||
var vii = vi.Read(file);
|
||||
AudioNormalization node = new();
|
||||
node.AllAudio = true;
|
||||
node.Pattern = "";
|
||||
node.NotMatching = true;
|
||||
var args = new NodeParameters(file, logger, false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => FfmpegPath;
|
||||
args.TempPath = TempPath;
|
||||
|
||||
const string ffmpeg = @"C:\utils\ffmpeg\ffmpeg.exe";
|
||||
new VideoFile().Execute(args);
|
||||
|
||||
AudioNormalization node = new();
|
||||
node.AllAudio = true;
|
||||
node.Pattern = "";
|
||||
node.NotMatching = true;
|
||||
//node.OutputFile = file + ".sup";
|
||||
var args = new FileFlows.Plugin.NodeParameters(file, logger, false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => ffmpeg;
|
||||
args.TempPath = @"D:\videos\temp";
|
||||
int output = node.Execute(args);
|
||||
string log = logger.ToString();
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
|
||||
new VideoFile().Execute(args);
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Pattern_Test3()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\test_orig.mkv";
|
||||
var logger = new TestLogger();
|
||||
var vi = new VideoInfoHelper(FfmpegPath, logger);
|
||||
var vii = vi.Read(file);
|
||||
|
||||
int output = node.Execute(args);
|
||||
string log = logger.ToString();
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Pattern_Test3()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\test_orig.mkv";
|
||||
var logger = new TestLogger();
|
||||
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", logger);
|
||||
var vii = vi.Read(file);
|
||||
AudioNormalization node = new();
|
||||
node.AllAudio = true;
|
||||
node.Pattern = "flac";
|
||||
node.NotMatching = false;
|
||||
var args = new NodeParameters(file, logger, false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => FfmpegPath;
|
||||
args.TempPath = TempPath;
|
||||
|
||||
const string ffmpeg = @"C:\utils\ffmpeg\ffmpeg.exe";
|
||||
new VideoFile().Execute(args);
|
||||
|
||||
AudioNormalization node = new();
|
||||
node.AllAudio = true;
|
||||
node.Pattern = "flac";
|
||||
node.NotMatching = false;
|
||||
//node.OutputFile = file + ".sup";
|
||||
var args = new FileFlows.Plugin.NodeParameters(file, logger, false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => ffmpeg;
|
||||
args.TempPath = @"D:\videos\temp";
|
||||
int output = node.Execute(args);
|
||||
string log = logger.ToString();
|
||||
Assert.AreEqual(2, output);
|
||||
}
|
||||
|
||||
new VideoFile().Execute(args);
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Pattern_Test4()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\test_orig.mkv";
|
||||
var logger = new TestLogger();
|
||||
var vi = new VideoInfoHelper(FfmpegPath, logger);
|
||||
var vii = vi.Read(file);
|
||||
|
||||
int output = node.Execute(args);
|
||||
string log = logger.ToString();
|
||||
Assert.AreEqual(2, output);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Pattern_Test4()
|
||||
{
|
||||
const string file = @"D:\videos\unprocessed\test_orig.mkv";
|
||||
var logger = new TestLogger();
|
||||
var vi = new VideoInfoHelper(@"C:\utils\ffmpeg\ffmpeg.exe", logger);
|
||||
var vii = vi.Read(file);
|
||||
AudioNormalization node = new();
|
||||
node.AllAudio = true;
|
||||
var args = new NodeParameters(file, logger, false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => FfmpegPath;
|
||||
args.TempPath = TempPath;
|
||||
|
||||
const string ffmpeg = @"C:\utils\ffmpeg\ffmpeg.exe";
|
||||
new VideoFile().Execute(args);
|
||||
|
||||
AudioNormalization node = new();
|
||||
node.AllAudio = true;
|
||||
//node.Pattern = "truehd";
|
||||
//node.NotMatching = false;
|
||||
//node.OutputFile = file + ".sup";
|
||||
var args = new FileFlows.Plugin.NodeParameters(file, logger, false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => ffmpeg;
|
||||
args.TempPath = @"D:\videos\temp";
|
||||
int output = node.Execute(args);
|
||||
string log = logger.ToString();
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
|
||||
new VideoFile().Execute(args);
|
||||
|
||||
int output = node.Execute(args);
|
||||
string log = logger.ToString();
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AudioNormalization_Test_TwoPass_NegInfinity()
|
||||
{
|
||||
string file = TestFile_TwoPassNegInifinity;
|
||||
var vi = new VideoInfoHelper(FfmpegPath, new TestLogger());
|
||||
var vii = vi.Read(file);
|
||||
|
||||
AudioNormalization node = new();
|
||||
node.TwoPass = true;
|
||||
var args = new NodeParameters(file, new TestLogger(), false, string.Empty);
|
||||
args.GetToolPathActual = (string tool) => FfmpegPath;
|
||||
args.TempPath = TempPath;
|
||||
|
||||
new VideoFile().Execute(args);
|
||||
|
||||
int output = node.Execute(args);
|
||||
Assert.AreEqual(1, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public abstract class TestBase
|
||||
|
||||
protected string TestFile_BasicMkv => Path.Combine(TestPath, "basic.mkv");
|
||||
protected string TestFile_Pgs => Path.Combine(TestPath, "pgs.mkv");
|
||||
protected string TestFile_TwoPassNegInifinity => Path.Combine(TestPath, "audio_normal_neg_infinity.mkv");
|
||||
|
||||
private class TestSettings
|
||||
{
|
||||
|
||||
@@ -147,6 +147,7 @@ public class AudioNormalization: EncodingNode
|
||||
int index = output.LastIndexOf("{");
|
||||
if (index == -1)
|
||||
throw new Exception("Failed to detected json in output");
|
||||
|
||||
string json = output.Substring(index);
|
||||
json = json.Substring(0, json.IndexOf("}") + 1);
|
||||
if (string.IsNullOrEmpty(json))
|
||||
@@ -154,6 +155,13 @@ public class AudioNormalization: EncodingNode
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
LoudNormStats stats = JsonSerializer.Deserialize<LoudNormStats>(json);
|
||||
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
|
||||
if (stats.input_i == "-inf" || stats.input_lra == "-inf" || stats.input_tp == "-inf" || stats.input_thresh == "-inf" || stats.target_offset == "-inf")
|
||||
{
|
||||
args.Logger?.WLog("-inf detected in loud norm two pass, falling back to single pass loud norm");
|
||||
return $"loudnorm={LOUDNORM_TARGET}";
|
||||
}
|
||||
|
||||
string ar = $"loudnorm=print_format=summary:linear=true:{LOUDNORM_TARGET}:measured_I={stats.input_i}:measured_LRA={stats.input_lra}:measured_tp={stats.input_tp}:measured_thresh={stats.input_thresh}:offset={stats.target_offset}";
|
||||
return ar;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user