mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2025-12-30 13:20:02 -06:00
FF-1439 - added more options to convert audio
This commit is contained in:
@@ -2,7 +2,7 @@ namespace FileFlows.AudioNodes;
|
||||
|
||||
public class ConvertAudio : ConvertNode
|
||||
{
|
||||
protected override string Extension => Codec;
|
||||
protected override string DefaultExtension => Codec;
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/audio-nodes/convert-audio";
|
||||
|
||||
public static List<ListOption> BitrateOptions => ConvertNode.BitrateOptions;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -5,15 +5,13 @@ public class ConvertToAAC : ConvertNode
|
||||
/// <inheritdoc />
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/audio-nodes/convert-to-aac";
|
||||
/// <inheritdoc />
|
||||
protected override string Extension => "aac";
|
||||
protected override string DefaultExtension => "aac";
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "svg:aac";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if high efficiency should be used
|
||||
/// </summary>
|
||||
[Boolean(5)]
|
||||
[Boolean(6)]
|
||||
public bool HighEfficiency { get => base.HighEfficiency; set =>base.HighEfficiency = value; }
|
||||
|
||||
protected override bool SetId3Tags => true;
|
||||
}
|
||||
@@ -5,7 +5,7 @@ public class ConvertToMP3 : ConvertNode
|
||||
/// <inheritdoc />
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/audio-nodes/convert-to-mp3";
|
||||
/// <inheritdoc />
|
||||
protected override string Extension => "mp3";
|
||||
protected override string DefaultExtension => "mp3";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "svg:mp3";
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace FileFlows.AudioNodes;
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/audio-nodes/convert-to-ogg";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string Extension => "ogg";
|
||||
protected override string DefaultExtension => "ogg";
|
||||
|
||||
public static List<ListOption> BitrateOptions => ConvertNode.BitrateOptions;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ public class ConvertToWAV : ConvertNode
|
||||
/// <inheritdoc />
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/audio-nodes/convert-to-wav";
|
||||
/// <inheritdoc />
|
||||
protected override string Extension => "wav";
|
||||
protected override string DefaultExtension => "wav";
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "svg:wav";
|
||||
|
||||
|
||||
@@ -38,6 +38,12 @@
|
||||
"Bitrate-Help": "The bitrate for the new file, the higher the bitrate the better the quality but larger the file.",
|
||||
"Codec": "Codec",
|
||||
"Codec-Help": "The audio codec to convert the file into.",
|
||||
"SampleRate": "Sample Rate",
|
||||
"SampleRate-Help": "The sample rate to use",
|
||||
"Channels": "Channels",
|
||||
"Channels-Help": "The number of channels the converted file will have.\nIf you specify more channels than the source, FFmpeg will automatically up-mix it.\nIf you specify fewer channels than the source, FFmpeg will automatically down-mix it.",
|
||||
"CustomExtension": "Extension",
|
||||
"CustomExtension-Help": "Allows you to set a custom file extension to use instead of the automatic one determined by the codec.",
|
||||
"Normalize": "Normalize",
|
||||
"Normalize-Help": "If the audio should be normalized with two pass audio normalization",
|
||||
"SkipIfCodecMatches": "Skip If Codec Matches",
|
||||
@@ -57,6 +63,12 @@
|
||||
"Bitrate-Help": "The bitrate for the new AAC file, the higher the bitrate the better the quality but larger the file. 192 Kbps is the recommended rate.",
|
||||
"Normalize": "Normalize",
|
||||
"Normalize-Help": "If the audio should be normalized with two pass audio normalization",
|
||||
"SampleRate": "Sample Rate",
|
||||
"SampleRate-Help": "The sample rate to use",
|
||||
"Channels": "Channels",
|
||||
"Channels-Help": "The number of channels the converted file will have.\nIf you specify more channels than the source, FFmpeg will automatically up-mix it.\nIf you specify fewer channels than the source, FFmpeg will automatically down-mix it.",
|
||||
"CustomExtension": "Extension",
|
||||
"CustomExtension-Help": "Allows you to set a custom file extension to use instead of the automatic one determined by the codec.",
|
||||
"SkipIfCodecMatches": "Skip If Codec Matches",
|
||||
"SkipIfCodecMatches-Help": "If the existing audio codec matches, this file will not be processed regardless of the bitrate. Otherwise if off, the bitrate must be less than or equal to for it to skip.",
|
||||
"HighEfficiency": "High Efficiency",
|
||||
@@ -72,6 +84,12 @@
|
||||
"Fields": {
|
||||
"Bitrate": "Bitrate",
|
||||
"Bitrate-Help": "The bitrate for the new FLAC file, the higher the bitrate the better the quality but larger the file. 128 Kbps is the recommended rate.",
|
||||
"SampleRate": "Sample Rate",
|
||||
"SampleRate-Help": "The sample rate to use",
|
||||
"Channels": "Channels",
|
||||
"Channels-Help": "The number of channels the converted file will have.\nIf you specify more channels than the source, FFmpeg will automatically up-mix it.\nIf you specify fewer channels than the source, FFmpeg will automatically down-mix it.",
|
||||
"CustomExtension": "Extension",
|
||||
"CustomExtension-Help": "Allows you to set a custom file extension to use instead of the automatic one determined by the codec.",
|
||||
"Normalize": "Normalize",
|
||||
"Normalize-Help": "If the audio should be normalized with two pass audio normalization",
|
||||
"SkipIfCodecMatches": "Skip If Codec Matches",
|
||||
@@ -87,6 +105,12 @@
|
||||
"Fields": {
|
||||
"Bitrate": "Bitrate",
|
||||
"Bitrate-Help": "The bitrate for the new MP3 file, the higher the bitrate the better the quality but larger the file. 192 Kbps is the recommended rate.",
|
||||
"SampleRate": "Sample Rate",
|
||||
"SampleRate-Help": "The sample rate to use",
|
||||
"Channels": "Channels",
|
||||
"Channels-Help": "The number of channels the converted file will have.\nIf you specify more channels than the source, FFmpeg will automatically up-mix it.\nIf you specify fewer channels than the source, FFmpeg will automatically down-mix it.",
|
||||
"CustomExtension": "Extension",
|
||||
"CustomExtension-Help": "Allows you to set a custom file extension to use instead of the automatic one determined by the codec.",
|
||||
"Normalize": "Normalize",
|
||||
"Normalize-Help": "If the audio should be normalized with two pass audio normalization",
|
||||
"SkipIfCodecMatches": "Skip If Codec Matches",
|
||||
@@ -102,6 +126,12 @@
|
||||
"Fields": {
|
||||
"Bitrate": "Bitrate",
|
||||
"Bitrate-Help": "The bitrate for the new OGG file, the higher the bitrate the better the quality but larger the file. 128 Kbps is the recommended rate.",
|
||||
"SampleRate": "Sample Rate",
|
||||
"SampleRate-Help": "The sample rate to use",
|
||||
"Channels": "Channels",
|
||||
"Channels-Help": "The number of channels the converted file will have.\nIf you specify more channels than the source, FFmpeg will automatically up-mix it.\nIf you specify fewer channels than the source, FFmpeg will automatically down-mix it.",
|
||||
"CustomExtension": "Extension",
|
||||
"CustomExtension-Help": "Allows you to set a custom file extension to use instead of the automatic one determined by the codec.",
|
||||
"Normalize": "Normalize",
|
||||
"Normalize-Help": "If the audio should be normalized with two pass audio normalization",
|
||||
"SkipIfCodecMatches": "Skip If Codec Matches",
|
||||
@@ -117,6 +147,12 @@
|
||||
"Fields": {
|
||||
"Bitrate": "Bitrate",
|
||||
"Bitrate-Help": "The bitrate for the new WAV file, the higher the bitrate the better the quality but larger the file. 128 Kbps is the recommended rate.",
|
||||
"SampleRate": "Sample Rate",
|
||||
"SampleRate-Help": "The sample rate to use",
|
||||
"Channels": "Channels",
|
||||
"Channels-Help": "The number of channels the converted file will have.\nIf you specify more channels than the source, FFmpeg will automatically up-mix it.\nIf you specify fewer channels than the source, FFmpeg will automatically down-mix it.",
|
||||
"CustomExtension": "Extension",
|
||||
"CustomExtension-Help": "Allows you to set a custom file extension to use instead of the automatic one determined by the codec.",
|
||||
"Normalize": "Normalize",
|
||||
"Normalize-Help": "If the audio should be normalized with two pass audio normalization",
|
||||
"SkipIfCodecMatches": "Skip If Codec Matches",
|
||||
|
||||
Reference in New Issue
Block a user