mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2026-02-06 17:38:25 -06:00
FF-1439 - added more options to convert audio
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using FileFlows.AudioNodes.Helpers;
|
||||
using System.ComponentModel;
|
||||
using FileFlows.AudioNodes.Helpers;
|
||||
|
||||
namespace FileFlows.AudioNodes
|
||||
{
|
||||
@@ -6,7 +7,10 @@ namespace FileFlows.AudioNodes
|
||||
|
||||
public abstract class ConvertNode:AudioNode
|
||||
{
|
||||
protected abstract string Extension { get; }
|
||||
/// <summary>
|
||||
/// Gets the default extension to use if none set
|
||||
/// </summary>
|
||||
protected abstract string DefaultExtension { get; }
|
||||
/// <summary>
|
||||
/// Gets or sets if using high efficiency
|
||||
/// </summary>
|
||||
@@ -18,14 +22,12 @@ namespace FileFlows.AudioNodes
|
||||
return info.Bitrate;
|
||||
}
|
||||
|
||||
protected virtual bool SetId3Tags => false;
|
||||
|
||||
public override int Inputs => 1;
|
||||
public override int Outputs => 2;
|
||||
|
||||
protected virtual List<string> GetArguments(NodeParameters args, out string? extension)
|
||||
{
|
||||
string Codec = Extension;
|
||||
string Codec = DefaultExtension;
|
||||
extension = null;
|
||||
string codecKey = Codec + "_codec";
|
||||
string codec = args.GetToolPathActual(codecKey)?.EmptyAsNull() ?? Codec;
|
||||
@@ -55,6 +57,12 @@ namespace FileFlows.AudioNodes
|
||||
}
|
||||
|
||||
int bitrate = Bitrate;
|
||||
List<string> ffArgs = new()
|
||||
{
|
||||
"-c:a",
|
||||
codec,
|
||||
};
|
||||
|
||||
if (Codec.ToLowerInvariant() == "mp3" || ogg || Codec.ToLowerInvariant() == "aac")
|
||||
{
|
||||
if (bitrate is >= 10 and <= 20)
|
||||
@@ -69,60 +77,56 @@ namespace FileFlows.AudioNodes
|
||||
|
||||
args.Logger?.ILog($"Using variable bitrate setting '{bitrate}' for codec '{Codec}'");
|
||||
|
||||
List<string> results;
|
||||
|
||||
if (codec == "libfdk_aac")
|
||||
{
|
||||
results = new()
|
||||
ffArgs.AddRange(new[]
|
||||
{
|
||||
"-c:a",
|
||||
codec,
|
||||
"-vbr",
|
||||
Math.Min(Math.Max(1, bitrate / 2), 5).ToString()
|
||||
};
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
results = new()
|
||||
ffArgs.AddRange(new[]
|
||||
{
|
||||
"-c:a",
|
||||
codec,
|
||||
"-qscale:a",
|
||||
bitrate.ToString()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
if (Codec == "aac" && HighEfficiency)
|
||||
{
|
||||
extension = "m4a";
|
||||
results.AddRange(new[] { "-profile:a", "aac_he_v2" });
|
||||
ffArgs.AddRange(new[] { "-profile:a", "aac_he_v2" });
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
else if(bitrate is > 10 and <= 20)
|
||||
{
|
||||
throw new Exception("Variable bitrate not supported in codec: " + Codec);
|
||||
}
|
||||
|
||||
if (bitrate == 0)
|
||||
else if (bitrate != 0)
|
||||
{
|
||||
// automatic
|
||||
return new List<string>
|
||||
ffArgs.AddRange(new []
|
||||
{
|
||||
"-c:a",
|
||||
codec
|
||||
};
|
||||
"-ab",
|
||||
(bitrate == -1 ? GetSourceBitrate(args).ToString() : bitrate + "k")
|
||||
});
|
||||
}
|
||||
|
||||
return new List<string>
|
||||
|
||||
if (SampleRate > 0)
|
||||
{
|
||||
"-c:a",
|
||||
codec,
|
||||
"-ab",
|
||||
(bitrate == -1 ? GetSourceBitrate(args).ToString() : bitrate + "k")
|
||||
};
|
||||
ffArgs.Add("-ar");
|
||||
ffArgs.Add(SampleRate.ToString());
|
||||
}
|
||||
|
||||
if (Channels > 0)
|
||||
{
|
||||
ffArgs.Add("-ac");
|
||||
ffArgs.Add(Channels.ToString());
|
||||
}
|
||||
|
||||
return ffArgs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -136,16 +140,85 @@ namespace FileFlows.AudioNodes
|
||||
[Select(nameof(BitrateOptions), 1)]
|
||||
public int Bitrate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sample rate
|
||||
/// </summary>
|
||||
[DefaultValue(0)]
|
||||
[Select(nameof(SampleRateOptions), 2)]
|
||||
public int SampleRate { get; set; }
|
||||
|
||||
private static List<ListOption> _SampleRateOptions;
|
||||
/// <summary>
|
||||
/// Gets the sample rate options
|
||||
/// </summary>
|
||||
public static List<ListOption> SampleRateOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_SampleRateOptions == null)
|
||||
{
|
||||
_SampleRateOptions = new List<ListOption>
|
||||
{
|
||||
new () { Label = "Automatic", Value = 0},
|
||||
new () { Label = "Same as source", Value = 1},
|
||||
new () { Label = "44100", Value = 44100 },
|
||||
new () { Label = "48000", Value = 48000 },
|
||||
new () { Label = "88200", Value = 88200 },
|
||||
new () { Label = "96000", Value = 96000 },
|
||||
new () { Label = "176400", Value = 176400 },
|
||||
new () { Label = "192000", Value = 192000 }
|
||||
};
|
||||
}
|
||||
return _SampleRateOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of channels rate
|
||||
/// </summary>
|
||||
[DefaultValue(0)]
|
||||
[Select(nameof(ChannelsOptions), 3)]
|
||||
public int Channels { get; set; }
|
||||
|
||||
private static List<ListOption> _ChannelsOptions;
|
||||
/// <summary>
|
||||
/// Gets the channel options
|
||||
/// </summary>
|
||||
public static List<ListOption> ChannelsOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_ChannelsOptions == null)
|
||||
{
|
||||
_ChannelsOptions = new List<ListOption>
|
||||
{
|
||||
new () { Label = "Same as source", Value = 0},
|
||||
new () { Label = "Mono", Value = 1f},
|
||||
new () { Label = "Stereo", Value = 2f},
|
||||
new () { Label = "5.1", Value = 6},
|
||||
new () { Label = "7.1", Value = 8}
|
||||
};
|
||||
}
|
||||
return _ChannelsOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a custom extension to override the ont to use
|
||||
/// </summary>
|
||||
[TextVariable(4)]
|
||||
public string CustomExtension { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the audio should be normalized
|
||||
/// </summary>
|
||||
[Boolean(3)]
|
||||
[Boolean(5)]
|
||||
public bool Normalize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if it should be skipped if the codec is the same
|
||||
/// </summary>
|
||||
[Boolean(4)]
|
||||
[Boolean(6)]
|
||||
[ConditionEquals(nameof(Normalize), true, inverse: true)]
|
||||
public bool SkipIfCodecMatches { get; set; }
|
||||
|
||||
@@ -224,26 +297,27 @@ namespace FileFlows.AudioNodes
|
||||
}
|
||||
string ffprobe = ffprobeResult.Value;
|
||||
|
||||
if(Normalize == false && AudioInfo.Codec?.ToLower() == Extension?.ToLower())
|
||||
if(Normalize == false && AudioInfo.Codec?.ToLower() == DefaultExtension?.ToLower())
|
||||
{
|
||||
if (SkipIfCodecMatches)
|
||||
{
|
||||
args.Logger?.ILog($"Audio file already '{Extension}' at bitrate '{AudioInfo.Bitrate} bps', and set to skip if codec matches");
|
||||
args.Logger?.ILog($"Audio file already '{DefaultExtension}' at bitrate '{AudioInfo.Bitrate} bps', and set to skip if codec matches");
|
||||
return 2;
|
||||
}
|
||||
|
||||
args.Logger?.ILog($"Comparing bitrate {AudioInfo.Bitrate} is less than or equal to {(Bitrate * 1000)}");
|
||||
if(AudioInfo.Bitrate <= Bitrate * 1000) // this bitrate is in Kbps, whereas AudioInfo.Bitrate is bytes per second
|
||||
{
|
||||
args.Logger?.ILog($"Audio file already '{Extension}' at bitrate '{AudioInfo.Bitrate} bps ({(AudioInfo.Bitrate / 1000)} KBps)'");
|
||||
args.Logger?.ILog($"Audio file already '{DefaultExtension}' at bitrate '{AudioInfo.Bitrate} bps ({(AudioInfo.Bitrate / 1000)} KBps)'");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var ffArgs = GetArguments(args, out string extension);
|
||||
string outputFile = FileHelper.Combine(args.TempPath,
|
||||
Guid.NewGuid() + "." + (extension?.EmptyAsNull() ?? Extension));
|
||||
string actualExt = args.ReplaceVariables(CustomExtension, stripMissing: true)?.EmptyAsNull() ??
|
||||
extension?.EmptyAsNull() ?? DefaultExtension;
|
||||
string outputFile = FileHelper.Combine(args.TempPath, Guid.NewGuid() + "." + actualExt.TrimStart('.'));
|
||||
|
||||
ffArgs.Insert(0, "-hide_banner");
|
||||
ffArgs.Insert(1, "-y"); // tells ffmpeg to replace the file if already exists, which it shouldnt but just incase
|
||||
|
||||
Reference in New Issue
Block a user